0Pricing
C Academy · บทเรียน

แทรกข้อมูลใน 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. โหนดและโครงสร้างต้นไม้
  2. แทรกข้อมูลใน BST
  3. การท่องต้นไม้
  4. ค้นหาและคืนหน่วยความจำ
← กลับไปที่ C Academy