首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言鏈表完全指南:單/雙向鏈表的創建、遍歷、插入、刪除與合併實戰

     編輯:關於C語言

C語言鏈表完全指南:單/雙向鏈表的創建、遍歷、插入、刪除與合併實戰

期末課程設計將C語言難度大幅提升,首次接觸分層架構(View/Service/Persistence),這一切的基礎都建立在鏈表操作之上。本文整理自《C語言程序設計教程》第十章,系統梳理鏈表核心操作,並附完整可運行代碼。

一、鏈表結構與靜態/動態鏈表

鏈表 vs 數組:

  • 數組需預先聲明大小,超長則溢出;鏈表可動態擴展。
  • 數組內存連續,同類型元素;鏈表通過 malloc 動態分配,用指針串聯,物理可不連續。

每個結點包含數據域和指針域(指向下一結點),末結點指針為 NULL。結構體定義:

struct Student {
    char cName[20];
    int iNumber;
    struct Student *next;  // 指向本結構體類型的指針
};
  • 靜態鏈表:用數組實現,鏈域存下標,受限於數組長度。
  • 動態鏈表:運行時逐個 malloc 結點,靈活無上限,工程首選。

二、單鏈表的建立與遍歷

單鏈表只有 next 指針,單向鏈接。採用尾插法創建:

struct Student *Create() {
    struct Student *pHead = NULL, *pEnd, *pNew;
    iCount = 0;
    pEnd = pNew = (struct Student *)malloc(sizeof(struct Student));
    scanf("%s%d", pNew->cName, &pNew->iNumber);  // 讀首結點
    while (pNew->iNumber != 0) {  // 學號為0結束
        iCount++;
        if (iCount == 1) {
            pNew->next = pHead;
            pEnd = pHead = pNew;
        } else {
            pNew->next = NULL;
            pEnd->next = pNew;
            pEnd = pNew;
        }
        pNew = (struct Student *)malloc(sizeof(struct Student));
        scanf("%s%d", pNew->cName, &pNew->iNumber);
    }
    free(pNew);  // 釋放最後多分配的結點
    return pHead;
}

遍歷輸出:

void print(struct Student *pHead) {
    struct Student *pTemp = pHead;
    int i = 1;
    printf("總共%d個學生:\n", iCount);
    while (pTemp != NULL) {
        printf("第%d個:姓名%s 學號%d\n", i++, pTemp->cName, pTemp->iNumber);
        pTemp = pTemp->next;
    }
}

三、單鏈表的插入與刪除

插入(按學號查找後插入)

struct Student *Insert(struct Student *pHead, int number) {
    struct Student *p = pHead, *pNew;
    while (p && p->iNumber != number) p = p->next;  // 定位
    pNew = (struct Student *)malloc(sizeof(struct Student));
    scanf("%s%d", pNew->cName, &pNew->iNumber);
    pNew->next = p->next;
    p->next = pNew;
    iCount++;
    return pHead;
}

刪除(按位置序號刪除)

void Delete(struct Student *pHead, int number) {
    struct Student *pTemp = pHead, *pPre = pTemp;
    for (int i = 0; i < number; i++) {
        pPre = pTemp;
        pTemp = pTemp->next;
    }
    pPre->next = pTemp->next;  // 斷鏈
    free(pTemp);               // 釋放內存
    iCount--;
}

四、雙向鏈表:概念、創建、遍歷與查找

雙向鏈表每結點有 llink(前驅)和 rlink(後繼)兩個指針,可雙向遍歷。結構:

typedef struct Node {
    char name[20];
    struct Node *llink, *rlink;
} STUD;

創建(構建循環雙向鏈表,頭結點 h 不存數據)

STUD *creat(int n) {
    STUD *h = (STUD *)malloc(sizeof(STUD));
    h->name[0] = '\0'; h->llink = NULL; h->rlink = NULL;
    STUD *p = h, *s;
    for (int i = 0; i < n; i++) {
        s = (STUD *)malloc(sizeof(STUD));
        printf("輸入第%d個姓名:", i+1);
        scanf("%s", s->name);
        p->rlink = s; s->llink = p; s->rlink = NULL;
        p = s;
    }
    h->llink = p; p->rlink = h;  // 首尾相連成環
    return h;
}

遍歷與查找

void print(STUD *h) {
    STUD *p = h->rlink;
    while (p != h) { printf("%s ", p->name); p = p->rlink; }
    printf("\n");
}

STUD *search(STUD *h, char *x) {
    STUD *p = h->rlink;
    while (p != h) {
        if (strcmp(p->name, x) == 0) return p;
        p = p->rlink;
    }
    printf("未找到!\n");
    return NULL;
}

五、循環鏈表與鏈表合併

  • 循環鏈表:末結點指向頭結點,成環。判斷尾結點只需檢查 next == head。無需專門頭結點。
  • 有序鏈表合併:兩鏈表按學號升序,合併後保持有序。用三指針 a/b/c 分別跟蹤兩鏈表當前結點與合併鏈表尾部,類似歸併排序合併步驟,時間複雜度 O(m+n)。
void merge(struct stud *La, struct stud *Lb) {
    struct stud *a = La->next, *b = Lb->next, *c = La;
    while (a && b) {
        if (a->num <= b->num) { c->next = a; c = a; a = a->next; }
        else { c->next = b; c = b; b = b->next; }
    }
    c->next = a ? a : b;
    free(Lb);  // 釋放Lb頭結點
}

六、拓展思維:多維鏈表

雙向鏈表增加一個指針域即可指向前驅;同理,再加 ulink/dlink 可構建二維鏈表(邏輯上),物理內存仍線性。三維、更高維同理可擴展,待數據結構課程深入探索。

總結

鏈表是C語言指針運用的集大成者。掌握結構體定義、malloc/free 內存管理、指針斷鏈與重鏈(插入/刪除核心)、遍歷邏輯,單向→雙向→循環層層遞進,再結合文件持久化,即可構建完整的數據管理系統(如影片信息管理系統)。代碼規範、邊界檢查(空指針、越界)是工程化關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved