經典常見的自平衡的二叉搜索樹(Self-balancing Binary Search Tree)有
① AVL樹 :Windows NT 內核中廣泛使用
② 紅黑樹:C++ STL(比如 map、set )Java 的 TreeMap、TreeSet、HashMap、HashSet Linux 的進程調度 Ngix 的 timer 管理
1 AVL樹 vs 紅黑樹
①AVL樹 平衡標准比較嚴格:每個左右子樹的高度差不超過1
最大高度是 1.44 ∗ log2 n + 2 − 1.328(100W個節點,AVL樹最大樹高28)
搜索、添加、刪除都是 O(logn) 復雜度,其中添加僅需 O(1) 次旋轉調整、刪除最多需要 O(logn) 次旋轉調整
② 紅黑樹 平衡標准比較寬松:沒有一條路徑會大於其他路徑的2倍
最大高度是 2 ∗ log2(n + 1)( 100W個節點,紅黑樹最大樹高40)
搜索、添加、刪除都是 O(logn) 復雜度,其中添加、刪除都僅需 O(1) 次旋轉調整
◼ 搜索的次數遠遠大於插入和刪除,選擇AVL樹;搜索、插入、刪除次數幾乎差不多,選擇紅黑樹
◼ 相對於AVL樹來說,紅黑樹犧牲了部分平衡性以換取插入/刪除操作時少量的旋轉操作,整體來說性能要優於AVL樹
◼ 紅黑樹的平均統計性能優於AVL樹,實際應用中更多選擇使用紅黑樹
2 AVL和紅黑樹各自數據結構
2.1 AVL樹
平衡因子(Balance Factor):某結點的左右子樹的高度差
AVL樹的特點:
1) 每個節點的平衡因子只可能是 1、0、-1(絕對值 ≤ 1,如果超過 1,稱之為“失衡”)
2) 每個節點的左右子樹高度差不超過 1
3) 搜索、添加、刪除的時間復雜度是 O(logn)
2.1.1 添加導致的失衡
◼ 示例:往下面這棵子樹中添加 13
◼ 最壞情況:可能會導致所有祖先節點都失衡
◼ 父節點、非祖先節點,都不可能失衡
①LL – 右旋轉(單旋)
②RR – 左旋轉(單旋)
③LR – RR左旋轉,LL右旋轉(雙旋)
④RL – LL右旋轉,RR左旋轉(雙旋)
2.1.2 刪除導致的失衡
◼ 示例:刪除子樹中的 16
◼ 可能會導致父節點或祖先節點失衡(只有1個節點會失衡),其他節點,都不可能失衡
①LL – 右旋轉(單旋)
◼ 如果綠色節點不存在,更高層的祖先節點可能也會失衡,需要再次恢復平衡,然后又可能導致更高層的祖先節點失衡...
◼ 極端情況下,所有祖先節點都需要進行恢復平衡的操作,共 O(logn) 次調整
② RR – 左旋轉(單旋)
③LR – RR左旋轉,LL右旋轉(雙旋)
④RL – LL右旋轉,RR左旋轉(雙旋)
2.1.2 AVL樹的總結:
① 添加
可能會導致所有祖先節點都失衡
只要讓高度最低的失衡節點恢復平衡,整棵樹就恢復平衡【僅需 O(1) 次調整】
② 刪除
可能會導致父節點或祖先節點失衡(只有1個節點會失衡)
恢復平衡后,可能會導致更高層的祖先節點失衡【最多需要 O(logn) 次調整】
平均時間復雜度
搜索:O(logn)
添加:O(logn),僅需 O(1) 次的旋轉操作
刪除:O(logn),最多需要 O(logn) 次的旋轉操作
2.2 紅黑樹
也叫做平衡二叉B樹(Symmetric Binary
◼ 紅黑樹必須滿足以下 5 條性質
1. 節點是 RED 或者 BLACK
2. 根節點是 BLACK
3. 葉子節點(外部節點,空節點)都是 BLACK
4. RED 節點的子節點都是 BLACK
① RED 節點的 parent 都是 BLACK
② 從根節點到葉子節點的所有路徑上不能有 2 個連續的 RED 節點
5.從任一節點到葉子節點的所有路徑都包含相同數目的BLACK 節點
2.2.1 紅黑樹和4階B樹(2-3-4樹)具有等價性
◼ BLACK 節點與它的 RED 子節點融合在一起,形成1個B樹節點
◼ 紅黑樹的 BLACK 節點個數 與 4階B樹的節點總個數 相等
◼ 網上有些教程:用 2-3樹 與 紅黑樹 進行類比,這是極其不嚴謹的,2-3樹 並不能完美匹配 紅黑樹 的所有情況
◼ 注意:因為PPT界面空間有限,后面展示的紅黑樹都會省略 NULL 節點
2.2.2 添加導致的失衡
2.2.3 刪除導致的失衡
2.2.4 紅黑樹性質總結
最初遺留的困惑:為何那5條性質,就能保證紅黑樹是平衡的?
p 那5條性質,可以保證 紅黑樹 等價於 4階B樹
◼ 相比AVL樹,紅黑樹的平衡標准比較寬松:沒有一條路徑會大於其他路徑的2倍
◼ 是一種弱平衡、黑高度平衡
◼ 紅黑樹的最大高度是 2 ∗ log2(n + 1) ,依然是 O(logn) 級別
◼ 搜索:O(logn)
◼ 添加:O(logn),O(1) 次的旋轉操作
◼ 刪除:O(logn),O(1) 次的旋轉操作