1. 程式人生 > >紅黑樹的快速實現

紅黑樹的快速實現

紅黑樹的概述:

紅黑樹本質上是一種二叉查詢樹,但它在二叉查詢樹的基礎上額外添加了一個標記(顏色),同時具有一定的規則。這些規則使紅黑樹保證了一種平衡,插入、刪除、查詢的最壞時間複雜度都為 O(logn)。

紅黑樹的性質:

1、每個節點要麼是紅色,要麼是黑色; 2、根節點永遠是黑色的; 3、所有的葉節點都是是黑色的(注意這裡說葉子節點其實是上圖中的 NIL 節點); 4、每個紅色節點的兩個子節點一定都是黑色; 5、從任一節點到其子樹中每個葉子節點的路徑都包含相同數量的黑色節點。

紅黑樹的旋轉

左旋:將一個向右傾斜的紅色連結旋轉為向左連結。對比操作前後,可以看出,該操作實際上是將紅線連結的兩個節點中的一個較大的節點移動到根節點上。

image

右旋:與左旋剛好相反,這裡就不贅述了,直接看圖。

image

紅黑樹的插入與調整

因為要滿足紅黑樹的這五條性質,如果我們插入的是黑色節點,那就違反了性質五,需要進行大規模調整;如果我們插入的是紅色節點,那就只有在要插入節點的父節點也是紅色的時候違反性質四或者當插入的節點是根節點時,違反性質二,所以,我們把要插入的節點的顏色變成紅色。

不需要調整的情況: 1、當插入的節點是根節點時,直接塗黑即可; 2、當要插入的節點的父節點是黑色的時候,這個時候插入一個紅色的節點並沒有對這五個性質產生破壞。所以直接插入不用在進行調整操作。

需要調整的情況:即插入節點的父結點也是紅色

。 因為左右對稱的緣故,在此只討論父結點位於祖父節點的左支的情況(N 為插入節點):

1、叔叔節點是紅色 這時候只進行換色操作:將父結點和叔叔節點塗成黑色,祖父節點塗成紅色。

image

2、叔叔節點是黑色,插入節點位於父節點的右支 這時候需要將父結點當成新的插入節點,並以他為支點進行左旋操作,進入情況3 。

image

3、叔叔節點是黑色,插入節點位於父結點的左支 這時候需要先進行換色操作:將父結點塗成黑色,祖父節點塗成紅色;然後進行右旋操作。

image

紅黑樹的刪除與調整

如果被刪除結點有孩子,則需要選一個合適的孩子節點作為新的根節點,稱為當前節點。 1、只有左孩子或只有右孩子,則讓該孩子作為當前節點替代被刪除結點; 2、左右孩子均存在,則用被刪除結點的中序後繼結點作為當前節點替代被刪除結點。

注意:替代只是值的互換,顏色不變。 即:當前節點是黑色,被刪除結點是紅色。替換後,當前節點位於被刪除結點的位置,是紅色;被刪除結點位於當前節點原來的位置,是黑色。

不需要調整的情況: 1、被刪除結點的是紅色的; 2、被刪除結點只有一個孩子,用孩子的值替換被刪除節點,刪除孩子結點。

需要調整的情況:(被刪除節點為黑色) 因為左右對稱的緣故,在此只討論父結點位於祖父節點的左支的情況: 1、兄弟節點為紅色 這時候需要互換父結點和兄弟節點的顏色,並進行左旋操作。

image

2、兄弟節點為黑色,且其左右孩子也為黑色 將兄弟節點塗成紅色,再將父結點當成新的被刪除結點(只是當成,並不刪除)進行一次調整(右圖中少了根節點的左孩子被刪除元素)。

image

3、兄弟節點為黑色,且其左孩子為紅色 先換色:左孩子塗成黑色,兄弟節點塗成紅色;再以兄弟節點為支點右旋。變成情況4 。

image

4、兄弟節點為黑色,且其右孩子為紅色 先換色:父結點的顏色賦給兄弟節點,父結點塗成黑色,兄弟節點的右孩子塗成黑色;再左旋(右圖中a 的左孩子是被刪除元素)。

image

紅黑樹的查詢

與二叉排序樹的查詢一樣:從根節點出發,待找值較大時往右子樹方向查詢,待找值較小時往左子樹方向查詢,直到找到匹配的結點。若找不到則查詢失敗。

紅黑樹的應用

Epoll 實現、Java集合中的 TreeSet 和 TreeMap、C++ STL 中的 set、map,以及 Linux 虛擬記憶體的管理,都是通過紅黑樹去實現的。 在平時也可以應用於各種管理系統的查詢演算法中,藉此提高效率。

線上生成紅黑樹

看完本教程,如果你還不太能清楚的寫出紅黑樹的構造過程,那麼,這一個網站將能很好地幫助到你。它不僅支援手動輸入結點值,也能隨機生成結點,更重要的是,該網站把每一次插入、刪除的調整步驟都展現了出來。趕緊試試吧!線上生成紅黑樹(含變形步驟)

更多內容請移步微信公眾號 “ 暗星湧動 ”