最近組內定個規矩,每週分享一個算法,上週是第一週,分享的是紅黑樹,下面是本身學習總結的,感受網上的都不是特別清楚,要麼是寫的特別複雜,沒有一點條理。php
1、紅黑樹性質html
1.每一個結點要麼是紅的要麼是黑的linux
2.根結點是黑的nginx
3.每一個葉結點(葉結點即指樹尾端NIL指針或NULL結點)都是黑的算法
4.若是一個結點是紅的,那麼它的兩個兒子都是黑的學習
5.對於任意結點而言,其到葉結點樹尾端NIL指針的每條路徑都包含相同數目的黑結點spa
總結:平衡狀態下紅黑樹要麼單支黑-紅,要麼有兩個子節點.net
2、複雜度指針
O(lgn)htm
3、結點插入
將一個節點插入到紅黑樹中,須要執行哪些步驟呢?首先,將紅黑樹看成一顆二叉查找樹,將節點插入;而後,將節點着色爲紅色;最後,經過旋轉和從新着色等方法來修正該樹,使之從新成爲一顆紅黑樹。
1.將插入的節點着色爲紅色,不會違背"特性(5)"!少違背一條特性,就意味着咱們須要處理的狀況越少。接下來,就要努力的讓這棵樹知足其它性質便可;知足了的話,它就又是一顆紅黑樹了
2.對於"特性4",是有可能違背的!
總之:新插入的結點是紅色!
3.插入的5種狀況:
(1)若是插入的是根結點,因爲原樹是空樹,此狀況只會違反性質2,所以直接把此結點塗爲黑色;
(2) 若是插入的結點的父結點是黑色,因爲此不會違反性質2和性質4,紅黑樹沒有被破壞,因此此時什麼也不作。
(3) 若是當前結點的父結點是紅色且祖父結點的另外一個子結點(叔叔結點)是紅色;
解決: 將當前節點的父節點和叔叔節點塗黑,祖父結點塗紅,把當前結點指向祖父節點,重新的當前節點從新開始算法。
如下(4)(5)都以左孩子爲例,右孩子進行對稱操做便可
(4)當前節點的父節點是紅色,叔叔節點是黑色,當前節點是其父節點的左孩子;
解決: 父節點變爲黑色,祖父節點變爲紅色,在祖父節點爲支點右旋。
(5)當前節點的父節點是紅色,叔叔節點是黑色,當前節點是其父節點的右子;
解決:當前節點的父節點作爲新的當前節點,以新當前節點爲支點左旋。問題轉爲(4)
總結:整個過程就是解決以上幾個問題,關鍵是整個過程要更新當前節點是哪一個結點
4、結點刪除
須要執行的操做依次是:首先,將紅黑樹看成一顆二叉查找樹,將該節點從二叉查找樹中刪除;而後,經過"旋轉和從新着色"等一系列來修正該樹,使之從新成爲一棵紅黑樹。
待刪除的節點按照兒子的個數能夠分爲三種:
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的狀況。
其中的左旋右旋其實也很簡單,有不清楚的你們上網查查,此處再也不詳細敘述了。
5、應用場景
1.著名的linux進程調度Completely Fair Scheduler,用紅黑樹管理進程控制塊
2.epoll在內核中的實現,用紅黑樹管理事件塊
3.nginx中,用紅黑樹管理timer等
4.Java的TreeMap實現
5.普遍用在C++的STL中。map和set都是用紅黑樹實現的。
6、其餘
從頭至尾的插入和刪除操做案例插圖:
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/