แทรกข้อมูลใน BST
สร้างต้นไม้ค้นหาแบบทวิภาค
แทรกข้อมูลใน BST เป็นบทเรียน C Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน
กฎการจัดเรียงของ BST
ต้นไม้ค้นหาแบบทวิภาค (BST) คือต้นไม้ทวิภาคที่มีกฎเพิ่มเติมว่า สำหรับทุกโหนด ค่าทั้งหมดในต้นไม้ย่อยด้านซ้ายต้องน้อยกว่า และค่าทั้งหมดในต้นไม้ย่อยด้านขวาต้องมากกว่า
การจัดเรียงนี้ทำให้เราค้นหา เพิ่ม และลบข้อมูลได้โดยใช้เวลาแปรผันตามความสูงของต้นไม้
ค่าควรอยู่ที่ใด
เมื่อต้องการเพิ่มข้อมูล เราเริ่มจากรากแล้วเปรียบเทียบ หากค่าใหม่เล็กกว่า เราไปทางซ้าย หากใหญ่กว่า เราไปทางขวา
ทำซ้ำจนถึงตำแหน่งว่าง (NULL) ซึ่งเป็นตำแหน่งที่โหนดใหม่ควรอยู่พอดี
/* insert 7 into:
* 10
* / \
* 5 15
* 7 < 10 -> left; 7 > 5 -> right of 5
*/ฟังก์ชันช่วย create_node
การเพิ่มข้อมูลจะสร้างโหนดใบไม้ใหม่ เราจึงนำตัวสร้างที่จัดสรรและเริ่มต้นโหนดกลับมาใช้ซ้ำ
โหนดลูกทั้งสองเริ่มต้นเป็น NULL เพราะโหนดที่เพิ่งเพิ่มเข้ามาจะเป็นใบไม้เสมอ
Node *create_node(int value) {
Node *n = malloc(sizeof(Node));
if (!n) return NULL;
n->value = value;
n->left = n->right = NULL;
return n;
}การเพิ่มข้อมูลแบบเรียกตัวเอง
วิธีเพิ่มข้อมูลที่เรียบง่ายที่สุดคือใช้การเรียกตัวเองและคืนค่ารากของต้นไม้ย่อยที่อาจเป็นโหนดใหม่
หากต้นไม้ย่อยว่าง ให้คืนโหนดใหม่ หากไม่ว่าง ให้เรียกตัวเองทางซ้ายหรือขวา แล้วเชื่อมผลลัพธ์กลับเข้าที่เดิม จากนั้นคืนรากเดิม
Node *insert(Node *root, int value) {
if (root == NULL)
return create_node(value);
if (value < root->value)
root->left = insert(root->left, value);
else if (value > root->value)
root->right = insert(root->right, value);
return root; /* equal: ignore duplicate */
}เหตุผลที่ต้องคืนค่าราก
การคืนค่ารากของต้นไม้ย่อยทำให้โหนดแม่เชื่อมลิงก์กลับได้ในบรรทัดเดียว: root->left = insert(root->left, v)
เมื่อต้นไม้ย่อยว่าง โหนดใหม่ที่คืนค่ามาจะกลายเป็นโหนดลูก หากไม่ว่าง จะคืนรากเดิมและลิงก์ยังคงไม่เปลี่ยนแปลง
/* The assignment does double duty:
* - empty case: stores the new node
* - non-empty: stores the same pointer back (no-op)
*/
root->left = insert(root->left, value);การจัดการค่าซ้ำ
BST ที่ใช้งานจริงต้องกำหนดว่าจะจัดการค่าที่เท่ากันอย่างไร ทางเลือกที่พบได้บ่อยคือไม่สนใจค่าซ้ำ เช่นเดียวกับที่ insert ของเราทำ โดยไม่มีแขนงสำหรับกรณีที่ค่าเท่ากัน
ทางเลือกอื่นคือเก็บตัวนับประจำแต่ละโหนด หรือส่งค่าซ้ำไปด้านใดด้านหนึ่งเสมอ
if (value < root->value)
root->left = insert(root->left, value);
else if (value > root->value)
root->right = insert(root->right, value);
/* value == root->value -> do nothing */การสร้าง BST
การเพิ่มค่าตามลำดับหนึ่งจะสร้างต้นไม้ที่รูปร่างขึ้นอยู่กับลำดับการเพิ่ม
ในที่นี้เราเพิ่มตัวเลขหลายค่าและแสดงโหนดลูกโดยตรงของราก เพื่อยืนยันว่ากฎการจัดเรียงยังคงถูกต้อง
#include <stdio.h>
#include <stdlib.h>
typedef struct Node { int value; struct Node *left, *right; } Node;
Node *create_node(int v){ Node *n=malloc(sizeof(Node)); n->value=v; n->left=n->right=NULL; return n; }
Node *insert(Node *r,int v){
if(!r) return create_node(v);
if(v<r->value) r->left=insert(r->left,v);
else if(v>r->value) r->right=insert(r->right,v);
return r;
}
int main(void){
Node *root = NULL;
int data[] = {10,5,15,3,7};
for(int i=0;i<5;i++) root=insert(root,data[i]);
printf("root=%d left=%d right=%d\n", root->value, root->left->value, root->right->value);
return 0;
}การเพิ่มข้อมูลแบบวนซ้ำ
คุณสามารถเพิ่มข้อมูลโดยไม่ใช้การเรียกตัวเองได้เช่นกัน เราเดินลงไปด้วยพอยน์เตอร์พร้อมจดจำโหนดแม่ไว้ จนกว่าจะพบตำแหน่งว่าง
จากนั้นเชื่อมโหนดใหม่เข้ากับด้านที่ถูกต้องของโหนดแม่นั้น
void insert_iter(Node **rootp, int value) {
Node *cur = *rootp, *parent = NULL;
while (cur) {
parent = cur;
cur = (value < cur->value) ? cur->left : cur->right;
}
Node *n = create_node(value);
if (!parent) *rootp = n;
else if (value < parent->value) parent->left = n;
else parent->right = n;
}ลำดับการเพิ่มกำหนดรูปร่างต้นไม้
การเพิ่ม 1,2,3,4,5 ตามลำดับที่เรียงแล้วทำให้เกิดต้นไม้เสื่อมรูปที่มีลักษณะเหมือนรายการเชื่อมโยง โดยมีความสูงเท่ากับจำนวนโหนด
การเพิ่มตามลำดับที่สมดุลช่วยให้ความสูงใกล้เคียง log(n) ความสมดุลส่งผลโดยตรงต่อความเร็วในการค้นหา
/* sorted insert 1..5 ->
* 1
* \
* 2
* \
* 3 (height = 4, like a list)
*/ต้นทุนของการเพิ่มข้อมูล
การเพิ่มแต่ละครั้งจะเดินไปตามเส้นทางหนึ่งจากรากถึงใบไม้ จึงใช้เวลาแปรผันตามความสูงของต้นไม้
สำหรับต้นไม้สมดุล จะมีการเปรียบเทียบประมาณ log(n) ครั้ง ส่วนต้นไม้เสื่อมรูปอาจใช้ n ครั้ง นี่คือเหตุผลที่มีต้นไม้แบบปรับสมดุลได้
สาธิตการแทรกแบบเต็ม
โปรแกรมนี้แทรกค่า จากนั้นนับจำนวนโหนดเพื่อยืนยันว่ามีการจัดเก็บค่าที่แตกต่างกันห้าค่า และค่าซ้ำถูกละเว้น
ค่า 10 ที่ซ้ำกันไม่ทำให้จำนวนเพิ่มขึ้น เพราะ insert จะตัดค่าที่เท่ากันออก
#include <stdio.h>
#include <stdlib.h>
typedef struct Node { int value; struct Node *left, *right; } Node;
Node *cn(int v){ Node *n=malloc(sizeof(Node)); n->value=v; n->left=n->right=NULL; return n; }
Node *insert(Node *r,int v){
if(!r) return cn(v);
if(v<r->value) r->left=insert(r->left,v);
else if(v>r->value) r->right=insert(r->right,v);
return r;
}
int count(Node *r){ return r? 1+count(r->left)+count(r->right):0; }
int main(void){
Node *root=NULL;
int d[]={10,5,15,10,20};
for(int i=0;i<5;i++) root=insert(root,d[i]);
printf("count=%d\n", count(root));
return 0;
}ตรวจสอบอย่างรวดเร็ว
วิเคราะห์พฤติกรรมของการแทรก
สรุปทบทวน
การแทรกใน BST จะเปรียบเทียบค่าใหม่กับแต่ละโหนด โดยไปทางซ้ายเมื่อมีค่าน้อยกว่า และไปทางขวาเมื่อมีค่ามากกว่า จนกว่าจะพบตำแหน่งว่าง
รูปแบบแบบเรียกซ้ำจะส่งคืนรากของต้นไม้ย่อย เพื่อให้โหนดแม่เชื่อมลิงก์กลับเข้าไปได้อย่างถูกต้อง ค่าใช้จ่ายของการแทรกขึ้นอยู่กับความสูงของต้นไม้ ดังนั้นลำดับการแทรกจึงมีความสำคัญ
คำถามที่พบบ่อย
บทเรียน “แทรกข้อมูลใน BST” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “แทรกข้อมูลใน BST” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “แทรกข้อมูลใน BST”
สร้างต้นไม้ค้นหาแบบทวิภาค คุณปฏิบัติ C Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน C Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “แทรกข้อมูลใน BST” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน C Academy นี้ได้ไหม
ได้ บทเรียน C Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- โหนดและโครงสร้างต้นไม้
- แทรกข้อมูลใน BST
- การท่องต้นไม้
- ค้นหาและคืนหน่วยความจำ