在《C語言實現非循環雙鏈表節點的刪除(不帶頭結點)》中,刪除頭節點、尾節點、中間節點分別需要不同邏輯,極易出錯。引入虛擬頭尾節點後,所有節點統一為「中間節點」,刪除邏輯簡化為兩行指針重連:
pMove->prior->next = pMove->next; pMove->next->prior = pMove->prior;
DeletePosList// 刪除第 pos 個節點 (1-based),成功返回 1
int DeletePosList(Node *pHead, Node *pTail, int pos) {
if (pos < 1) return 0; // 非法位置
Node *pMove = pHead->next; // 首個真實節點
int i = 1;
while (pMove != pTail) { // 未越過尾哨兵
if (i == pos) {
pMove->prior->next = pMove->next;
pMove->next->prior = pMove->prior;
free(pMove);
pMove = NULL;
printf("%s: 刪除 pos=%d 成功\n", __FUNCTION__, pos);
return 1;
}
i++;
pMove = pMove->next;
}
printf("%s: 刪除 pos=%d 失敗(越界)\n", __FUNCTION__, pos);
return 0;
}
DeleteValueList// 刪除第一個值為 x 的節點,成功返回 1
int DeleteValueList(Node *pHead, Node *pTail, int x) {
Node *pMove = pHead->next;
while (pMove != pTail) {
if (pMove->element == x) {
pMove->prior->next = pMove->next;
pMove->next->prior = pMove->prior;
free(pMove);
pMove = NULL;
printf("%s: 刪除值 x=%d 成功\n", __FUNCTION__, x);
return 1;
}
pMove = pMove->next;
}
printf("%s: 刪除值 x=%d 失敗(不存在)\n", __FUNCTION__, x);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int element;
struct Node *prior, *next;
} Node;
// 初始化帶頭尾節點的空鏈表
void InitList(Node **ppHead, Node **ppTail) {
*ppHead = (Node *)malloc(sizeof(Node));
*ppTail = (Node *)malloc(sizeof(Node));
(*ppHead)->next = *ppTail;
(*ppTail)->prior = *ppHead;
(*ppHead)->prior = (*ppTail)->next = NULL;
}
// 尾插建立測試數據 10 20 30 40 50
void BuildDemo(Node *pHead, Node *pTail) {
for (int v = 10; v <= 50; v += 10) {
Node *p = (Node *)malloc(sizeof(Node));
p->element = v; p->prior = p->next = NULL;
p->prior = pTail->prior;
p->next = pTail;
pTail->prior->next = p;
pTail->prior = p;
}
}
// 正向列印
void PrintList(Node *pHead, Node *pTail) {
for (Node *p = pHead->next; p != pTail; p = p->next)
printf("%d ", p->element);
printf("\n");
}
int main() {
Node *pHead, *pTail;
InitList(&pHead, &pTail);
BuildDemo(pHead, pTail);
printf("初始: "); PrintList(pHead, pTail); // 10 20 30 40 50
DeletePosList(pHead, pTail, 3); // 刪除第 3 個 (30)
printf("刪除第3個: "); PrintList(pHead, pTail); // 10 20 40 50
DeleteValueList(pHead, pTail, 10); // 刪除值 10
printf("刪除值10: "); PrintList(pHead, pTail); // 20 40 50
DeletePosList(pHead, pTail, 100); // 越界測試
DeleteValueList(pHead, pTail, 999); // 不存在測試
// 釋放所有節點(含頭尾)略
return 0;
}
free 後立即置 NULL,防野指針。完整項目代碼見 GitHub:DeleteNodeDoubleLinkedList_HeadList。