
Linked List 是面試必考、實務少用、但觀念影響深遠的資料結構。
先講結論
Linked List 的插入刪除只需要改指標,O(1) 搞定。代價是你沒辦法直接跳到第 i 個節點——得從頭走過去。跟 Array 比起來,它們的優缺點幾乎完全相反。
指標串起來的節點
每個節點存兩樣東西:資料本身,和指向下一個節點的指標。
head
↓
[10|→] → [20|→] → [30|→] → [40|→] → null
記憶體不連續,散落各處,靠指標串起來。這和 Array 的「一排連續格子」完全不同。
Array vs Linked List:一張表說完
| Array | Linked List | |
|---|---|---|
| 記憶體 | 連續 | 分散 |
| 隨機存取 | O(1) | O(n) 從頭走 |
| 頭部插入 | O(n) 搬移 | O(1) 改指標 |
| 中間插入 | O(n) 搬移 | O(1) 改指標(但走到那裡要 O(n)) |
| cache 友善度 | 極高 | 極低 |
最後一點很關鍵:現代 CPU 的 cache 機制偏愛連續記憶體。Linked List 的節點散落各處,每次走一步就可能 cache miss。這就是為什麼理論上 Linked List 在某些操作比較快,但實際跑起來 Array 常常贏——cache 效應太強了。
插入只改兩個指標
在 index 1 插入 15:
原本: [10] → [20] → [30]
Step 1: 新節點指向 [20]
[15] → [20]
Step 2: [10] 改指向 [15]
[10] → [15] → [20] → [30]
不用搬任何資料,只改兩個指標。這是 Linked List 最大的賣點。
刪除同理——把前一個節點跳過被刪的,指向下一個就好。被跳過的節點沒人引用,GC 會處理。
雙向鏈結串列:多花一點記憶體,換回便利
單向鏈結串列有個痛點:你只能往前走,不能往回。想刪最後一個節點?你得從頭走到倒數第二個。
雙向鏈結串列每個節點多存一個 prev 指標:
null ← [10] ⇄ [20] ⇄ [30] → null
removeLast 從 O(n) 變成 O(1)。Java 的 LinkedList 就是雙向實作。
環狀鏈結串列:尾巴接頭
[10] → [20] → [30] → [10] → ...(繞圈)
經典應用是 Round-Robin 排程——任務一個接一個輪流執行,跑完最後一個回到第一個。
老實說,什麼時候真的會用?
在大多數業務場景,你不太會直接用 Linked List。Array(動態陣列)在實務上幾乎全面碾壓。
但 Linked List 的觀念無處不在:
- LRU Cache 用雙向鏈結串列維護使用順序
- 作業系統的 process scheduling
- React Fiber 的工作單元就是一種鏈表結構
- Git 的 commit history 本質上也是
所以與其說「學 Linked List 要拿來用」,不如說「理解指標操作」本身就是程式設計的基本功。面試官考你 reverse linked list 不是在刁難你,是在看你會不會操作指標。好吧,也有一點在刁難你。
Linked List 就像手動排檔——你不會每天開,但懂了它你才真的理解變速箱怎麼運作的。