有了虛擬頭尾節點,刪除任意位置/值節點只需統一的指針重連:
/* 刪除第 pos 個有效節點 (1-based) */
bool List_ErasePos(DList *L, int pos) {
Node *p = L->head->next;
for (int i = 1; p != L->tail; p = p->next, ++i) {
if (i == pos) {
p->prior->next = p->next;
p->next->prior = p->prior;
free(p);
return true;
}
}
return false;
}
/* 刪除第一個值為 val 的節點 */
bool List_EraseVal(DList *L, int val) {
for (Node *p = L->head->next; p != L->tail; p = p->next) {
if (p->element == val) {
p->prior->next = p->next;
p->next->prior = p->prior;
free(p);
return true;
}
}
return false;
}
prior/next 永遠有效指向鄰居。p,再 free(p),防止野指針。
/* 無哨兵刪除首節點 */
if (p == head) {
head = p->next;
if (head) head->prior = NULL;
free(p);
}
/* 無哨兵刪除尾節點 */
if (p->next == NULL) {
p->prior->next = NULL;
free(p);
}
/* 無哨兵刪除中間節點 */
p->prior->next = p->next;
p->next->prior = p->prior;
free(p);
三段重複邏輯,易漏邊界,代碼膨脹 3 倍。
int main(void) {
DList L; List_Init(&L);
List_PushBack(&L, 10);
List_PushBack(&L, 20);
List_PushBack(&L, 30); // 10 20 30
List_ErasePos(&L, 2); // 刪除 20
List_PrintForward(&L); // 10 30
List_EraseVal(&L, 10); // 刪除 10
List_PrintForward(&L); // 30
List_EraseVal(&L, 30); // 刪除 30 (唯一節點)
List_PrintForward(&L); // 空
free(L.head); free(L.tail);
return 0;
}