紅黑樹#

為什麼需要平衡樹?#

普通 BST 在頻繁插入刪除後可能退化成連結串列,時間複雜度從 O(log n) 退化到 O(n)。

平衡的意義:保持樹的高度接近 log n,確保操作效率穩定。

紅黑樹的定義#

紅黑樹是一種近似平衡的二元搜尋樹,需滿足:

  1. 節點是紅色黑色
  2. 根節點是黑色
  3. 葉節點 (NIL) 是黑色(空節點)
  4. 紅色節點的子節點必為黑色(不能有連續紅節點)
  5. 從任一節點到其所有葉節點的路徑,黑色節點數量相同

條件 3 的 NIL 節點是為了簡化實作,實際上可共用同一個黑色空節點。

為什麼是「近似」平衡?#

樹類型高度平衡嚴格度
AVL 樹≈ log₂n嚴格(左右高度差 ≤ 1)
紅黑樹≤ 2log₂n寬鬆(最長路徑 ≤ 2 倍最短)

推導

  1. 去除紅節點後,黑節點形成的樹高度 ≤ log₂n
  2. 紅節點不能連續,加回紅節點後高度 ≤ 2log₂n

為什麼工程偏好紅黑樹?#

特性AVL 樹紅黑樹
查詢效率略優稍遜
插入/刪除調整頻繁調整較少
實作複雜度較複雜較簡單
適用場景讀多寫少讀寫均衡

工程結論:紅黑樹性能穩定,適合需要頻繁動態更新的場景。Java 的 TreeMap、C++ 的 map 都採用紅黑樹。

平衡調整基本操作#

旋轉#

  • 左旋 (Left Rotation):將右子節點提升為父節點
  • 右旋 (Right Rotation):將左子節點提升為父節點

插入後調整#

新插入節點預設為紅色,可能違反「不能有連續紅節點」的規則。

三種調整情況

CASE 1:叔叔節點是紅色

  • 父節點、叔叔節點變黑
  • 祖父節點變紅
  • 關注節點移到祖父節點

CASE 2:叔叔是黑色,當前節點是父的右子節點

  • 對父節點左旋
  • 轉換為 CASE 3

CASE 3:叔叔是黑色,當前節點是父的左子節點

  • 對祖父節點右旋
  • 父節點與祖父節點交換顏色

學習建議

  • 理解紅黑樹的用途和性質即可
  • 不需要背誦旋轉細節(工程中不會手寫)
  • 如需手動實現平衡樹,跳表是更簡單的替代方案