帶頭結點單鏈表刪除節點時,無需區分首節點、中間節點、尾節點。通過維護 pre (前驅) 和 cur (當前) 兩個指針,從頭結點開始遍歷,統一執行 pre->next = cur->next; free(cur); 即可完成所有位置的刪除。本文提供按位置刪除與按值刪除兩種模式的標準實現。
DeletePosNodeNode* DeletePosNode(Node *head, int pos) {
// pos: 1-based 位置 (第一個數據節點為 1)
if (pos < 1) { printf("位置非法: %d\n", pos); return head; }
Node *pre = head;
Node *cur = head->next;
int i = 1;
// 1. 遍歷找到第 pos 個節點及其前驅
while (cur && i < pos) {
pre = cur;
cur = cur->next;
i++;
}
// 2. 合法性檢查
if (!cur) {
printf("位置 %d 超出鏈表長度 (%d)\n", pos, i-1);
return head;
}
// 3. 統一刪除邏輯:斷開鏈接 + 釋放內存
pre->next = cur->next;
free(cur);
cur = NULL; // 防野指針
printf("刪除位置 %d 節點成功\n", pos);
return head;
}
DeleteValueNode (刪除首個匹配值)Node* DeleteValueNode(Node *head, int x) {
Node *pre = head;
Node *cur = head->next;
// 1. 遍歷查找值為 x 的節點
while (cur && cur->element != x) {
pre = cur;
cur = cur->next;
}
// 2. 未找到
if (!cur) {
printf("值 %d 不存在於鏈表中\n", x);
return head;
}
// 3. 統一刪除邏輯 (同按位置刪除)
pre->next = cur->next;
free(cur);
cur = NULL;
printf("刪除值 %d 節點成功\n", x);
return head;
}
刪除位置 2 (值 20) / 刪除值 20:
head -> [10] -> [20] -> [30] -> NULL
pre cur
執行 pre->next = cur->next; free(cur);
head -> [10] ----------> [30] -> NULL
pre (cur已釋放)
刪除位置 1 (首節點) / 刪除首節點值:
head -> [10] -> [20] -> NULL
pre cur
執行 pre->next = cur->next; // head->next 直接指向 20
head ----------> [20] -> NULL
刪除尾節點:
head -> [10] -> [20] -> NULL
pre cur
執行 pre->next = cur->next; // cur->next 為 NULL
head -> [10] -> NULL
// 無頭結點刪除首節點
if (pos == 1) {
Node *tmp = head;
head = head->next;
free(tmp);
return head; // 必須返回新 head!
}
// 無頭結點刪除尾節點
if (cur->next == NULL) { pre->next = NULL; free(cur); }
// 無頭結點刪除中間
pre->next = cur->next; free(cur);
帶頭結點版本:零 if-else 分支,統一邏輯覆蓋所有情況。
int main() {
Node *list; InitialList(&list);
CreateList(list); // 輸入: 10 20 30 40 0
PrintList(list); // 10 20 30 40
DeletePosNode(list, 2); // 刪除 20
PrintList(list); // 10 30 40
DeleteValueNode(list, 40); // 刪除尾部 40
PrintList(list); // 10 30
DeleteValueNode(list, 10); // 刪除首部 10
PrintList(list); // 30
DeletePosNode(list, 1); // 刪除唯一節點 30
PrintList(list); // (空)
DeletePosNode(list, 1); // 空表刪除,報錯
return 0;
}
pre = cur; cur = cur->next; 保證 pre 永遠是 cur 的前驅。帶頭結點單鏈表刪除操作,通過「哨兵節點 + 雙指針遍歷」模式,將原本需要 3-4 個分支處理的邊界情況,壓縮為單一統一邏輯。這不僅減少代碼量,更從根本上消除了邊界條件遺漏導致的 Bug,是「用空間換取邏輯簡潔性」的教科書級範例。