資料結構之「紅黑樹」

清塵閒聊發表於2019-04-02

紅黑樹

紅黑樹(Red–black tree)是一種自平衡二叉查詢樹。紅黑樹是每個節點都帶有顏色屬性的二叉查詢樹,顏色為紅色或黑色。

紅黑樹的特性:
1.節點要麼是紅色要麼就是黑色,不能沒有顏色。
2.根節點是黑色的。
3.所有葉子節點都是黑色的。
4.每個紅色節點必須有兩個黑色的子節點。
5.從任一節點到其每個葉子的所有簡單路徑都包含相同數目的黑色節點。

紅黑樹

從根節點到葉子節點的最長路徑不會超過最短路徑的 2 倍,所以它對查詢、刪除和新增的最差時間複雜度為 O(log n),且葉子上沒有資料儲存。

紅黑樹的實現

在 AVL樹 插入中,插入後導致不平衡,我們使用旋轉來保證它的平衡性。在紅黑樹中,我們使用 重新著色旋轉 來進行平衡。 首先,我們嘗試重新著色,如果重新著色滿足不了紅黑樹的特性,那麼我們就進行旋轉。

插入演算法主要有兩種情況,取決於叔叔節點的顏色。如果叔叔節點是紅色的,就進行重新著色。如果叔叔節點是黑色的,就要進行旋轉和(或)重新著色操作。

左旋和右旋請先參考《資料結構之「AVL樹」》。

新新增的節點設定為紅色。如果設為黑色,就會導致根到葉子節點的路徑上有一條路上,多一個額外的黑節點,這個是很難調整的。但是設為紅色節點後,可能會導致出現兩個連續紅色節點的衝突,那麼可以通過重新著色和樹旋轉來調整。

假如新插入的節點為 x:
1.按標準的二叉搜尋樹插入節點顏色為紅色的新節點。

2.假如 x 就是根節點,那麼改變 x 節點顏色為黑色。

3.如果新節點的父節點是黑色的,直接返回。

4.如果父節點和叔叔節點都是紅色的,需要改變父節點和叔叔節點的顏色為黑色,並設定祖父節點為紅色,如果祖父節點為根節點,設定祖父節點顏色為黑色。

5.如果父節點是紅色而叔叔節點是黑色或缺少,新節點是父節點的左子節點,而父節點又是其父節點的左子節點。這種情況就需要對祖父節點進行一次右旋,然後在切換父節點和祖父節點的顏色,就滿足紅黑樹的性質了。

6.如果父節點是紅色,而叔叔節點是黑色或缺少,並且新節點是其父節點的右子節點而父節點又是其父節點的左子節點。需要先對當前節點節點進行左旋,變成 情形5,然後按 情形5 的步驟操作來。

總結

與 AVL樹 相比,AVL樹 更加平衡,但它可能在插入和刪除期間引 起更多旋轉。因此,如果頻繁的插入和刪除操作,那麼應該首選紅黑樹。如果插入和刪除頻率較低且搜尋是更頻繁的操作,那麼AVL樹應優先於紅黑樹。

紅黑樹犧牲了部分平衡性以換取插入/刪除操作時做少量的旋轉操作,整體來說效能要優於AVL樹。

在 JDK 中,都是用紅黑樹來做 TreeSet 和 TreeMap 的資料結構儲存,在 JDK1.8之後都是用紅黑樹來儲存雜湊衝突大於等於八個節點的資料結構,所以紅黑樹還是一種比較常用的資料結構。

PS:
清山綠水始於塵,博學多識貴於勤。
我有酒,你有故事嗎?
公眾號:「清塵閒聊」。
歡迎一起談天說地,聊程式碼。

資料結構之「紅黑樹」

相關文章