無頭結點的非循環雙向鏈表在刪除節點時,需同時維護 prior(前驅)與 next(後繼)兩個指針,且必須單獨處理首節點、尾節點、唯一節點三種邊界情況,邏輯較單向鏈表複雜。本文提供兩種刪除模式的完整實現:按位置刪除與按值刪除。
typedef struct Node {
int element;
struct Node *prior;
struct Node *next;
} Node;
deletePosList關鍵邏輯分層:
pNode == NULL 直接返回。pos==1 && size==1,釋放節點並返回 NULL。pos==1,頭指針後移,新首節點 prior=NULL,釋放舊首節點。pos != size,斷開雙向連結 pMove->prior->next = pMove->next; pMove->next->prior = pMove->prior;。pos == size,前驅節點 next=NULL,釋放尾節點。deleteValueList邏輯結構類似,但遍歷條件變為 pMove->element == x。同樣需分別處理:
// 輔助函數:獲取鏈表長度
int sizeList(Node *pNode) {
int count = 0;
while (pNode) { count++; pNode = pNode->next; }
return count;
}
// 刪除 pos 位置節點
Node *deletePosList(Node *pNode, int pos) {
if (!pNode) { printf("鏈表為空\n"); return NULL; }
int size = sizeList(pNode);
if (pos < 1 || pos > size) { printf("位置非法\n"); return pNode; }
Node *pMove = pNode;
int i = 1;
// 情況 1:刪除唯一節點
if (size == 1) {
free(pNode);
return NULL;
}
// 情況 2:刪除首節點
if (pos == 1) {
pNode = pNode->next;
pNode->prior = NULL;
free(pMove);
return pNode;
}
// 遍歷至目標位置
while (pMove && i < pos) {
pMove = pMove->next;
i++;
}
// 情況 3:刪除尾節點
if (pMove->next == NULL) {
pMove->prior->next = NULL;
free(pMove);
return pNode;
}
// 情況 4:刪除中間節點
pMove->prior->next = pMove->next;
pMove->next->prior = pMove->prior;
free(pMove);
return pNode;
}
// 刪除值為 x 的首個節點
Node *deleteValueList(Node *pNode, int x) {
if (!pNode) return NULL;
Node *pMove = pNode;
while (pMove) {
if (pMove->element == x) {
// 唯一節點
if (pMove->prior == NULL && pMove->next == NULL) {
free(pMove); return NULL;
}
// 首節點
if (pMove->prior == NULL) {
pNode = pMove->next;
pNode->prior = NULL;
free(pMove);
return pNode;
}
// 尾節點
if (pMove->next == NULL) {
pMove->prior->next = NULL;
free(pMove);
return pNode;
}
// 中間節點
pMove->prior->next = pMove->next;
pMove->next->prior = pMove->prior;
free(pMove);
return pNode;
}
pMove = pMove->next;
}
printf("值 %d 不存在\n", x);
return pNode;
}
free,防止野指針訪問。head = deletePosList(head, 1))。next 都必須同步修改對應節點的 prior,反之亦然。無頭結點雙向鏈表刪除操作的核心難點在於邊界條件的窮盡處理。通過分類討論(空表、單節點、首節點、尾節點、中間節點),配合嚴謹的指針操作順序,可構建健壯的刪除函數。掌握此邏輯,有助於深入理解 Linux 內核 list_head、C++ STL list 等高級容器的底層實現原理。