完整簡單的紅黑樹算法


最近組內定個規矩,每周分享一個算法,上周是第一周,分享的是紅黑樹,下面是自己學習總結的,感覺網上的都不是特別清楚,要么是寫的特別復雜,沒有一點條理。

一、紅黑樹性質

1.每個結點要么是紅的要么是黑的

2.根結點是黑的

3.每個葉結點(葉結點即指樹尾端NIL指針或NULL結點)都是黑的

4.如果一個結點是紅的,那么它的兩個兒子都是黑的

5.對於任意結點而言,其到葉結點樹尾端NIL指針的每條路徑都包含相同數目的黑結點

總結:平衡狀態下紅黑樹要么單支黑-紅,要么有兩個子節點

二、復雜度

O(lgn)

三、結點插入

將一個節點插入到紅黑樹中,需要執行哪些步驟呢?首先,將紅黑樹當作一顆二叉查找樹,將節點插入;然后,將節點着色為紅色;最后,通過旋轉和重新着色等方法來修正該樹,使之重新成為一顆紅黑樹。

1.將插入的節點着色為紅色,不會違背"特性(5)"!少違背一條特性,就意味着我們需要處理的情況越少。接下來,就要努力的讓這棵樹滿足其它性質即可;滿足了的話,它就又是一顆紅黑樹了

 2.對於"特性4",是有可能違背的!

總之:新插入的結點是紅色!

3.插入的5種情況:

 (1)如果插入的是根結點,由於原樹是空樹,此情況只會違反性質2,因此直接把此結點塗為黑色;

 2 如果插入的結點的父結點是黑色,由於此不會違反性質2和性質4,紅黑樹沒有被破壞,所以此時什么也不做。

 3 如果當前結點的父結點是紅色且祖父結點的另一個子結點(叔叔結點)是紅色;

       解決: 將當前節點的父節點和叔叔節點塗黑,祖父結點塗紅,把當前結點指向祖父節點,從新的當前節點重新開始算法。

插入第3種情況

以下(4)(5)都以左孩子為例,右孩子進行對稱操作即可

  (4)當前節點的父節點是紅色,叔叔節點是黑色,當前節點是其父節點的左孩子;

      解決: 父節點變為黑色,祖父節點變為紅色,在祖父節點為支點右旋。

 

 插入的第4種情況

 

 

5當前節點的父節點是紅色,叔叔節點是黑色,當前節點是其父節點的右子;

解決:當前節點的父節點做為新的當前節點,以新當前節點為支點左旋。問題轉為(4

插入的第5種情況

總結:整個過程就是解決以上幾個問題,關鍵是整個過程要更新當前節點是哪個結點

 

四、結點刪除

需要執行的操作依次是:首先,將紅黑樹當作一顆二叉查找樹,將該節點從二叉查找樹中刪除;然后,通過"旋轉和重新着色"等一系列來修正該樹,使之重新成為一棵紅黑樹。

待刪除的節點按照兒子的個數可以分為三種:

1.刪除葉結點(沒有子結點) 

 (1)如果葉結點為紅色,直接刪除

刪除的第一種情況

(2)如果葉結點為黑色,兄弟結點沒有子結點

 解決: 兄弟節點B繪為紅色,父節點P繪為黑色。

 刪除的第二種情況

 

注意:之后操作的結點全為左孩子,右孩子進行對稱操作即可

   (3)葉結點為黑色,兄弟結點有一個孩子不為NIL。若這個孩子為右孩子。

解決:將B的這個右孩子繪為黑色,B繪為其父節點P原來的顏色,P繪為黑色,然后對P進行一次左旋轉。

 

 輸出的第三種情況

(4)葉結點為黑色,兄弟結點有一個孩子不為NIL,若這個孩子為左孩子。

    解決:將B的這個左孩子繪為黑色,B繪為紅色,然后對B進行一次右旋轉,問題轉化為右孩子的情況。

 

 刪除的第四種情況

(5)葉結點為黑色,兄弟結點有兩個孩子。 若兄弟結點(B)為紅色,則B的兩個孩子一定為黑色。

解決:將B繪為黑色,B的左孩子繪為紅色,然后對P(父結點)進行一次左旋轉。

 刪除的第五種情況

  (6)葉結點為黑色,兄弟結點(B)有兩個孩子。 若B為黑色,則B的兩個孩子一定為紅色。

解決:將B的父節點P繪為黑色,B的右孩子繪為黑色,B繪為其父節點P原來的顏色,然后對P進行一次左旋轉。

刪除的第六種情況

2.刪除結點有一個外部結點(有一個子結點, 這個結點C一定是紅色節點,否則從D到各個NIL節點的路徑上的黑色節點數目就會不同)

解決:交換D(刪除結點)和C(子結點)的內容(顏色保持不變),被刪除節點變為C,問題轉化為被刪除節點的兩個孩子都為NIL的情況。重新查看樹是否滿足紅黑樹。

3.刪除結點有兩個外部結點(有兩個子結點)

解決:按照二叉查找樹刪除節點的方法找到D的后繼節點S,交換D和S的內容(顏色保持不變),被刪除節點變為S,如果S有不為NIL的節點,那么繼續用S的后繼節點替換S(此過程可能是一級一級找,也可能是直接找左子樹的最大值,取決於本來要刪除的結點和實際刪除結點的值的大小,要刪除的結點比實際刪除的結點小,一級一級找,否則相反),直到被刪除節點的兩個孩子都為NIL,問題轉化為被刪除節點D的兩個孩子都為NIL的情況。

 刪除的第三大情況

 

 

其中的左旋右旋其實也很簡單,有不清楚的大家上網查查,此處不再詳細敘述了。

 

五、應用場景

1.著名的linux進程調度Completely Fair Scheduler,用紅黑樹管理進程控制塊

2.epoll在內核中的實現,用紅黑樹管理事件塊

3.nginx中,用紅黑樹管理timer等

4.Java的TreeMap實現

5.廣泛用在C++的STL中。map和set都是用紅黑樹實現的。

 

六、其他

從頭到尾的插入和刪除操作案例插圖:

http://blog.csdn.net/v_july_v/article/details/6284050

 

nginx 紅黑樹的實現(c實現)

http://blog.csdn.net/liuxuejiang158blog/article/details/21417145

 

c的紅黑樹實現

http://www.cnblogs.com/skywang12345/p/3624177.html#a3

 

php的紅黑樹實現

http://www.zhangley.com/article/php_rbtree/

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM