單鏈表插入時,首節點需修改頭指針 `head`,其它節點修改前驅節點的 `link` 域,看似兩種情況。本文揭示 **「每個節點都有一個指向它的指針」** 這一本質,通過**指向指針的指針** 統一處理,代碼更簡潔、無特殊分支。
typedef struct NODE {
struct NODE *link;
int value;
} Node;
Node *head = NULL; // 根指針,僅含指針域
首節點由 `head` 指向,其它節點由前驅節點的 `link` 指向。**統一觀點:每個節點背後都有一個 `Node*` 類型指針變量指向它。**
int insert(Node **linkp, int new_value) {
Node *current;
Node *new_node;
// 1. 尋找插入位置:linkp 始終指向「指向當前節點的指針」
while ((current = *linkp) != NULL && current->value < new_value)
linkp = ¤t->link; // 關鍵:移動到下一個節點的 link 域地址
// 2. 分配新節點
new_node = (Node *)malloc(sizeof(Node));
if (!new_node) return FALSE;
new_node->value = new_value;
// 3. 插入:統一操作 *linkp = new_node
new_node->link = current;
*linkp = new_node;
return TRUE;
}
假設鏈表 `3 → 7 → 10`,插入 `5`:
**首節點插入同理**:`linkp` 仍為 `&head`,`*linkp = new_node` 直接修改 `head`,無需特判!
int main() {
Node *head = NULL;
Node one = {NULL, 5}, second = {NULL, 10};
head = &one; one.link = &second;
insert(&head, 3); // 插入首部
// 鏈表變為 3 → 5 → 10
}
「消除特殊情況的關鍵在於承認:首節點的前驅指針就是頭指針。」
這種「指針的指針」模式廣泛適用於鏈表刪除、查找、反轉等操作,是 C 語言指針進階的必修範式。掌握它,鏈表代碼不再充斥 `if (prev == NULL)` 分支。