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

ลิงก์ลิสต์แบบสองทาง

ลิงก์สองทิศทาง

ลิงก์ลิสต์แบบสองทาง เป็นบทเรียน C Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน

ตัวเชื่อมโยงสองทาง

รายการเชื่อมโยงแบบสองทางให้ตัวชี้แก่แต่ละโหนดสองตัว ได้แก่ ตัวหนึ่งชี้ไปยังโหนด next และอีกตัวชี้ไปยังโหนด prev (โหนดก่อนหน้า)

วิธีนี้ทำให้เดินรายการได้ทั้งสองทิศทางและทำให้การลบง่ายขึ้น

#include <stdio.h>

struct Node {
    int value;
    struct Node *prev;
    struct Node *next;
};

int main(void) {
    printf("Each node links forward and backward\n");
    return 0;
}

การกำหนดโหนด

โครงสร้างจะเพิ่มตัวชี้ prev ควบคู่กับ next โดยทั้งสองค่าจะเป็น NULL ที่ปลายทั้งสองด้านของรายการ

#include <stdio.h>
#include <stdlib.h>

struct Node { int value; struct Node *prev; struct Node *next; };

int main(void) {
    struct Node *n = malloc(sizeof(struct Node));
    n->value = 1; n->prev = NULL; n->next = NULL;
    printf("%d\n", n->value);
    free(n);
    return 0;
}

ตัวช่วยสร้าง

เช่นเดียวกับก่อนหน้านี้ ตัวช่วยจะรวมการจัดสรรหน่วยความจำไว้ในที่เดียว และกำหนดทั้ง prev และ next เป็น NULL

#include <stdio.h>
#include <stdlib.h>

struct Node { int value; struct Node *prev; struct Node *next; };

struct Node *make(int v) {
    struct Node *n = malloc(sizeof(struct Node));
    n->value = v; n->prev = NULL; n->next = NULL;
    return n;
}

int main(void) {
    struct Node *n = make(42);
    printf("%d\n", n->value);
    free(n);
    return 0;
}

เชื่อมโหนดทั้งสองทิศทาง

เมื่อเชื่อมโหนดสองโหนด คุณต้องปรับปรุงการเชื่อมโยงทั้งสองทิศทาง ได้แก่ next ของโหนดแรกและ prev ของโหนดที่สอง

#include <stdio.h>
#include <stdlib.h>

struct Node { int value; struct Node *prev; struct Node *next; };
struct Node *make(int v){struct Node*n=malloc(sizeof*n);n->value=v;n->prev=NULL;n->next=NULL;return n;}

int main(void) {
    struct Node *a = make(1), *b = make(2);
    a->next = b;
    b->prev = a;
    printf("forward %d, back %d\n", a->next->value, b->prev->value);
    free(a); free(b);
    return 0;
}

แทรกที่ด้านหน้า

การเพิ่มโหนดไว้ด้านหน้า: next ของโหนดใหม่คือหัวรายการเดิม prev ของหัวรายการเดิมคือโหนดใหม่ จากนั้นเลื่อนหัวรายการไปยังโหนดใหม่

#include <stdio.h>
#include <stdlib.h>

struct Node { int value; struct Node *prev; struct Node *next; };
struct Node *make(int v){struct Node*n=malloc(sizeof*n);n->value=v;n->prev=NULL;n->next=NULL;return n;}

void push(struct Node **head, int v) {
    struct Node *n = make(v);
    n->next = *head;
    if (*head) (*head)->prev = n;
    *head = n;
}

int main(void) {
    struct Node *head = NULL;
    push(&head, 2); push(&head, 1);
    printf("%d %d\n", head->value, head->next->value);
    return 0;
}

การท่องไปข้างหน้า

การเดินไปข้างหน้าเหมือนกับรายการเชื่อมโยงแบบทางเดียวทุกประการ โดยติดตาม next จนถึง NULL

#include <stdio.h>
#include <stdlib.h>

struct Node { int value; struct Node *prev; struct Node *next; };
struct Node *make(int v){struct Node*n=malloc(sizeof*n);n->value=v;n->prev=NULL;n->next=NULL;return n;}

int main(void) {
    struct Node *a = make(1), *b = make(2);
    a->next = b; b->prev = a;
    for (struct Node *p = a; p; p = p->next) printf("%d ", p->value);
    printf("\n");
    free(a); free(b);
    return 0;
}

การท่องย้อนกลับ

ข้อได้เปรียบสำคัญคือ จากโหนดใด ๆ คุณสามารถเดินย้อนกลับได้โดยติดตามตัวชี้ prev จนถึงหัวรายการ

#include <stdio.h>
#include <stdlib.h>

struct Node { int value; struct Node *prev; struct Node *next; };
struct Node *make(int v){struct Node*n=malloc(sizeof*n);n->value=v;n->prev=NULL;n->next=NULL;return n;}

int main(void) {
    struct Node *a = make(1), *b = make(2), *c = make(3);
    a->next = b; b->prev = a; b->next = c; c->prev = b;
    for (struct Node *p = c; p; p = p->prev) printf("%d ", p->value);
    printf("\n");
    free(a); free(b); free(c);
    return 0;
}

การลบทำได้ง่ายขึ้น

เนื่องจากแต่ละโหนดรู้จักโหนดก่อนหน้า คุณจึงลบโหนดได้โดยไม่ต้องค้นหาโหนดก่อนหน้า

เพียงเชื่อม node->prev เข้ากับ node->next ในทั้งสองทิศทาง

#include <stdio.h>
#include <stdlib.h>

struct Node { int value; struct Node *prev; struct Node *next; };
struct Node *make(int v){struct Node*n=malloc(sizeof*n);n->value=v;n->prev=NULL;n->next=NULL;return n;}

void del(struct Node **head, struct Node *n) {
    if (n->prev) n->prev->next = n->next; else *head = n->next;
    if (n->next) n->next->prev = n->prev;
    free(n);
}

int main(void) {
    struct Node *a = make(1), *b = make(2), *c = make(3);
    a->next=b; b->prev=a; b->next=c; c->prev=b;
    struct Node *head = a;
    del(&head, b);
    printf("%d %d\n", head->value, head->next->value);
    return 0;
}

ปรับปรุงโหนดข้างเคียงทั้งสอง

เมื่อนำโหนดออก ต้องแก้ไขค่า next ของโหนดก่อนหน้า และค่า prev ของโหนดถัดไปเสมอ

ตรวจสอบค่า NULL ที่ปลายแต่ละด้าน เพื่อไม่ให้ไล่ตามตัวชี้ไปยังโหนดข้างเคียงที่ไม่มีอยู่

#include <stdio.h>
#include <stdlib.h>

struct Node { int value; struct Node *prev; struct Node *next; };
struct Node *make(int v){struct Node*n=malloc(sizeof*n);n->value=v;n->prev=NULL;n->next=NULL;return n;}

int main(void) {
    struct Node *a = make(1), *b = make(2);
    a->next = b; b->prev = a;
    a->next = NULL;
    free(b);
    printf("now only %d remains\n", a->value);
    free(a);
    return 0;
}

เก็บตัวชี้ท้ายรายการ

รายการเชื่อมโยงแบบสองทางจำนวนมากยังเก็บตัวชี้ท้ายรายการไปยังโหนดสุดท้ายด้วย ทำให้เพิ่มต่อท้ายและท่องย้อนกลับจากท้ายรายการได้ในเวลา O(1)

#include <stdio.h>
#include <stdlib.h>

struct Node { int value; struct Node *prev; struct Node *next; };
struct Node *make(int v){struct Node*n=malloc(sizeof*n);n->value=v;n->prev=NULL;n->next=NULL;return n;}

int main(void) {
    struct Node *head = make(1), *tail = head;
    struct Node *n = make(2);
    tail->next = n; n->prev = tail; tail = n;
    printf("tail = %d\n", tail->value);
    free(head); free(n);
    return 0;
}

ข้อแลกเปลี่ยน

รายการเชื่อมโยงแบบสองทางใช้หน่วยความจำเพิ่มขึ้น โดยมีตัวชี้เพิ่มอีกหนึ่งตัวต่อโหนด และต้องปรับปรุงการเชื่อมโยงสองรายการทุกครั้งที่มีการเปลี่ยนแปลง

สิ่งที่ได้กลับมาคือการท่องรายการสองทิศทางและการลบโหนดที่ทราบตำแหน่งได้ในเวลา O(1) ให้เลือกใช้ตามความต้องการของคุณ

#include <stdio.h>

int main(void) {
    printf("Singly: less memory, one-way\n");
    printf("Doubly: more memory, two-way + easy delete\n");
    return 0;
}

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ทดสอบความเข้าใจเกี่ยวกับรายการเชื่อมโยงแบบสองทาง

สรุปทบทวน

คุณได้เรียนรู้รายการเชื่อมโยงแบบสองทางแล้ว:

  • แต่ละโหนดมีตัวชี้ทั้ง prev และ next
  • การเชื่อมโหนดต้องปรับปรุงการเชื่อมโยงทั้งสองทิศทาง
  • คุณสามารถท่องไปข้างหน้าและย้อนกลับ และลบโหนดที่ทราบตำแหน่งได้ในเวลา O(1)
  • ข้อเสียคือใช้หน่วยความจำเพิ่มและต้องปรับปรุงตัวชี้มากขึ้น ส่วนตัวชี้ท้ายรายการช่วยให้เพิ่มต่อท้ายได้ในเวลา O(1)

คำถามที่พบบ่อย

บทเรียน “ลิงก์ลิสต์แบบสองทาง” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ลิงก์ลิสต์แบบสองทาง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ลิงก์ลิสต์แบบสองทาง”

ลิงก์สองทิศทาง คุณปฏิบัติ C Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “ลิงก์ลิสต์แบบสองทาง” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C Academy นี้ได้ไหม

ได้ บทเรียน C Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

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

  1. ลิงก์ลิสต์แบบทางเดียว
  2. การแทรกและการลบ
  3. การท่องผ่านและการค้นหา
  4. ลิงก์ลิสต์แบบสองทาง
← กลับไปที่ C Academy