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

C 語言鏈表節點刪除:三種情況的統一處理與完整實作

     編輯:關於C語言

刪除節點的三種情況

  1. 刪除首節點:將表頭指標指向第二個節點。
  2. 刪除尾節點:將倒數第二個節點的 next 設為 NULL。
  3. 刪除中間節點:將前驅節點的 next 指向被刪節點的後繼。

核心難點在於找到被刪節點的前驅,需遍歷鏈表。

完整代碼實作

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

struct Node { int num; struct Node *next; };
typedef struct Node *Link;

/* 列印 */
void printList(Link head) {
    while (head) { printf("[%d]", head->num); head = head->next; }
    putchar('\n');
}

/* 建立鏈表(無虛擬表頭版本) */
Link createList(int *arr, int len) {
    if (len == 0) return NULL;
    Link head = (Link)malloc(sizeof(struct Node));
    if (!head) return NULL;
    head->num = arr[0]; head->next = NULL;
    Link tail = head;
    for (int i = 1; i < len; ++i) {
        Link node = (Link)malloc(sizeof(struct Node));
        if (!node) return NULL;
        node->num = arr[i]; node->next = NULL;
        tail->next = node; tail = node;
    }
    return head;
}

/* 查找節點(返回節點指標) */
Link findNode(Link head, int num) {
    while (head) {
        if (head->num == num) return head;
        head = head->next;
    }
    return NULL;
}

/* 刪除指定節點 */
Link deleteNode(Link head, Link target) {
    if (target == head) {           // 情況 1:刪除首節點
        Link newHead = head->next;
        free(head);
        return newHead;
    }
    Link prev = head;
    while (prev->next != target)    // 找前驅
        prev = prev->next;

    if (target->next == NULL)       // 情況 2:刪除尾節點
        prev->next = NULL;
    else                            // 情況 3:刪除中間節點
        prev->next = target->next;

    free(target);
    return head;
}

/* 主程式互動測試 */
int main() {
    int data[6] = {1,2,3,4,5,6};
    Link head = createList(data, 6);
    if (!head) { puts("記憶體配置失敗"); return 1; }

    printf("原始鏈表:"); printList(head);

    while (1) {
        int num;
        printf("請輸入要刪除的編號 (-1 結束):");
        if (scanf("%d", &num) != 1 || num == -1) break;

        Link target = findNode(head, num);
        if (!target) { puts("未找到"); continue; }

        head = deleteNode(head, target);
        printf("刪除後:"); printList(head);
    }
    return 0;
}

關鍵技巧解析

  • 統一前驅查找:無論刪除哪種位置,先定位前驅 prev,再統一處理 prev->next 重連。
  • 首節點特判:無前驅時直接更新 head 指標並釋放原首節點。
  • 記憶體釋放:free(target) 必須在重連指標之後,避免野指標。
  • 無虛擬表頭版本:教學用途常見;工程上推薦「帶虛擬表頭」版本(見上一篇),可省去首節點特判。

常見錯誤避坑

  1. 忘記檢查 malloc 返回值。
  2. 刪除尾節點時未將前驅 next 設為 NULL,導致殘留懸空指標。
  3. 先 free 再訪問 target->next 取後繼,屬未定義行為。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved