紅黑樹分析筆記
閱讀本文的前提
1、知道二叉查詢樹的概念,插入、刪除和查詢操作;
2、知道二叉樹的左旋和右旋。
3、瞭解二叉平衡樹(AVL樹)的概念
紅黑樹的概念
紅黑樹是一種自平衡的二叉查詢樹,查詢、插入和刪除的平均時間複雜度是O(logN)。紅黑樹的每個節點都有一個顏色值(紅或黑),具有以下性質:
1、每個節點不是黑色就是紅色;
2、根節點是黑色;
3、如果一個節點是紅色,則該節點的左、右孩子節點必須是黑色;
4、每一個null葉子節點是黑色;
5、從任一個節點到null葉子節點的所有路徑上必須包含相同數量的黑色節點。
null葉子節點
在紅黑樹裡,存在兩種葉子節點,一種葉子節點是我們常說的葉子節點——左右孩子節點都為null,另外一種是null葉子節點,如下圖的紅黑樹:
插入操作
紅黑樹的插入操作分兩步:插入、調整。
插入操作和二叉查詢樹的操作一樣,找到合適的位置建立節點插入;
由於插入新節點後,可能會違背紅黑樹的性質,因此需要做調整處理。
規定插入節點為紅色
原因:如果新插入的節點為紅色,首先肯定不會違背性質5,方便接下來的調整。
調整規則
定義:
【當前節點】:插入節點
【父親節點】:【當前節點】的父親節點
【叔叔節點】:【當前節點】的父親節點的兄弟節點
【祖父節點】:【當前節點】的父親節點的父親節點
注:1、【當前節點】的值可能在調整過程中發生變化,不一定是開始的插入節點,【父親節點】、【叔叔節點】、【祖父節點】的值依賴於【當前節點】。
2、【叔叔節點】可以是NULL節點
case 1 : 【父親節點】是黑色
處 理:無須處理
case 2 : 【父親節點】是紅色,【叔叔節點】節點是紅色
處 理:【父親節點】和【叔叔節點】變黑,【祖父節點】變紅,將【祖父節點】設為【當前節點】,繼續按規則反覆調整。
case 3 : 【父親節點】是紅色,【叔叔節點】節點是黑色
處 理:這種情況又分4種小情況來處理
3-1-1【父親節點】是【祖父節點】的左孩子節點,【當前節點】是【父親節點】的左孩子節點
處 理:【父親節點】變黑,【祖父節點】變紅,以【祖父節點】右旋;
3-1-2【父親節點】是【祖父節點】的左孩子節點,【當前節點】是【父親節點】的右孩子節點
處 理:以【父親節點】左旋,變成上述3-1-1情形,旋轉後的【父親節點】設為【當前節點】,繼續調整;
3-2-1 【父親節點】是【祖父節點】的右孩子節點、【當前節點】是【父親節點】的左孩子節點
處 理:以【父親節點】右旋,變成下述3-2-2情形,旋轉後的【父親節點】設為【當前節點】,繼續調整;
3-2-2【父親節點】是【祖父節點】的右孩子節點、【當前節點】是【父親節點】的右孩子節點
處 理:以【祖父節點】左旋,【祖父節點】變紅,【父親節點】變黑;
刪除操作
首先要明白二叉查詢樹的刪除規則:
1、刪除節點是葉子節點,直接刪除;
2、刪除節點存在一個非空的子節點,刪除節點後,將子節點移至刪除節點位置;
3、刪除節點左右孩子節點均非空,則要從左或右子樹中查詢到後繼節點【後續節點的概念請看二叉查詢樹】,用後繼節點替換刪除節點,此時後繼節點成為新的刪除節點,後繼節點最多隻有一個非空的子節點,此時轉化為情況2。
紅黑樹的刪除規則和二叉查詢樹一致,關鍵要把握住一點,下面所說的刪除節點不一定是指一開始要刪除的節點,可能是情況3中的後續節點。
刪除操作是否要調整
如果刪除節點是紅色,按二叉排序樹的刪除規則刪除即可,不需要做任何調整;
原因:刪除節點是紅色,刪除後,不會違背紅黑樹的任一條性質。
如果刪除節點是黑色,按二叉排序樹的刪除規則冊除後需要做調整;
原因:會違背性質5,即從任一個節點到null葉子節點的所有路徑上的黑色節點的數量會不一樣。
調整規則
定義:
【當前節點】x: 刪除節點
【父親節點】p:【當前節點】的父親節點
【兄弟節點】b:【當前節點】的兄弟節點
注:【當前節點】的值可能在調整過程中發生變化,不一定是刪除節點。
只分析【當前節點】是【父親節點】的左孩子節點的情況,【當前節點】是【父親節點】的右孩子節點的情況的調整規則和前者類似,只是映象操作。
case 1 : 【兄弟節點】是紅色
處 理:【兄弟節點】變黑,【父親節點】變紅,以【父親節點】左旋,將【父親節點】的當前右孩子節點設為【兄弟節點】,繼續調整
case 2 : 【兄弟節點】是黑色且【兄弟節點】的左、右孩子節點均是黑色
處 理:【兄弟節點】變紅,將【父親節點】設為【當前節點】,繼續調整
case 3 : 【兄弟節點】是黑色且【兄弟節點】的左孩子節點是紅,右孩子節點是黑
處 理:將【兄弟節點】的左孩子節點變黑,【兄弟節點】變紅,以【兄弟節點】右旋,將【父親節點】的當前右孩子節點設為【兄弟節點】,繼續調整
case 4 : 【兄弟節點】是黑色且【兄弟節點】的右孩子節點是紅,左孩子節點顏色隨意
處 理:【兄弟節點】染成【父親節點】的顏色,【父親節點】變黑,【兄弟節點】的右孩子節點變黑,以【父親節點】左旋,演算法結束
注:上述圖只是演示操作過程,並不是顯示一顆完整的紅黑樹。
紅黑樹的用途
Java中的TreeMap和TreeSet都是用紅黑樹實現。在Java8後,HashMap在解決雜湊衝突時使用的連結串列長度大於8時會轉化為紅黑樹。
程式碼實現
https://github.com/melodylzl/DataStructAndAlgorithms/blob/master/RBTree/RBTree.java