算法基礎: 什麼是紅黑樹?

學習紅黑樹之前,需要先了解 二叉尋找樹(Binary Search Tree).

一. 二叉查找樹

1. 二叉查找樹(BST)特徵

(1) 左子樹上室友節點的值均小於或等於它的根節點的值.
(2) 右子樹上室友節點的值均大於或等於它的根節點的值.
(3) 左、右子樹也分別爲二叉排序樹.

下圖就是一顆典型的二叉查找樹:
在這裏插入圖片描述
這樣的數據結構有什麼好處?我們以查找節點爲10的數爲例:

1.查看根節點9:

在這裏插入圖片描述

2.由於10 > 9,因此查看右孩子13:

在這裏插入圖片描述

3.由於10 < 13,因此查看左孩子11:

在這裏插入圖片描述

4.由於10 < 11,因此查看左孩子10,發現10正是要查找的節點:

在這裏插入圖片描述

2.二叉樹的優點

這種方式正是二分查找的思想,查找所需的最大次數等同於二叉查找樹的高度. 在插入節點的時候也是利用類似的方法,通過一層一層比較大小,找到新節點適合插入的位置.

3.二叉樹的缺陷

二叉樹的缺陷主要體現在插入新節點上.

假設初始的二叉查找樹只有三個節點,根節點值爲9,左孩子值爲8,右孩子值爲12:
在這裏插入圖片描述

接下來我們依次插入如下五個節點:7,6,5,4,3。依照二叉查找樹的特性,結果會變成什麼樣呢?
在這裏插入圖片描述

上圖的形態雖然也符合二叉樹的特徵,但是查找的性能大打折扣,幾乎變成了線性.

如何解決二叉查找樹多次插入新節點而導致的不平衡呢? 於是就產生了 紅黑樹.

二.紅黑樹

紅黑樹(Read Black Tree) 是一種自平衡的二叉查找樹.除了符合二叉查找樹的基本特性外,它還具備以下附加特徵(必須同時滿足)

1.節點是紅色或黑色。
2.根節點是黑色。
3.每個葉子節點都是黑色的空節點(NIL節點)。
4 每個紅色節點的兩個子節點都是黑色。(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點)
5.從任一節點到其每個葉子的所有路徑都包含相同數目的黑色節點。

下圖中這棵樹,就是一顆典型的紅黑樹:
在這裏插入圖片描述正是因爲這些規則限制,才保證了紅黑樹的自平衡.紅黑樹從根到葉子的最長路徑不會超過最短路徑的2倍.

當插入或刪除節點的時候,紅黑樹的規則有可能被打破.這時候就需要做出一些調整,來繼續維持我們的規則.

什麼情況下會破壞紅黑樹的規則,什麼情況下不會破壞規則呢?我們舉兩個簡單的栗子:

1.向原紅黑樹插入值爲14的新節點:

在這裏插入圖片描述由於父節點15是黑色節點,因此這種情況並不會破壞紅黑樹的規則,無需做任何調整。

2.向原紅黑樹插入值爲21的新節點:

在這裏插入圖片描述由於父節點22是紅色節點,因此這種情況打破了紅黑樹的規則4(每個紅色節點的兩個子節點都是黑色),必須進行調整,使之重新符合紅黑樹的規則。

調整有兩種方法: 變色、旋轉.而旋轉又分成兩種形式: 左旋轉、右旋轉.

變色:

爲了重新符合紅黑樹的規則,嘗試把紅色節點變爲黑色,或者把黑色節點變爲紅色。

下圖所表示的是紅黑樹的一部分,需要注意節點25並非根節點。因爲節點21和節點22連續出現了紅色,不符合規則4,所以把節點22從紅色變成黑色:
在這裏插入圖片描述但這樣並不算完,因爲憑空多出的黑色節點打破了規則5,所以發生連鎖反應,需要繼續把節點25從黑色變成紅色:
在這裏插入圖片描述
此時仍然沒有結束,因爲節點25和節點27又形成了兩個連續的紅色節點,需要繼續把節點27從紅色變成黑色:

左旋轉:

逆時針旋轉紅黑樹的兩個節點,使得父節點被自己的右孩子取代,而自己成爲自己的左孩子。說起來很怪異,大家看下圖:
在這裏插入圖片描述圖中,身爲右孩子的Y取代了X的位置,而X變成了自己的左孩子。此爲左旋轉。

右旋轉:

順時針旋轉紅黑樹的兩個節點,使得父節點被自己的左孩子取代,而自己成爲自己的右孩子。大家看下圖:
在這裏插入圖片描述圖中,身爲左孩子的Y取代了X的位置,而X變成了自己的右孩子。此爲右旋轉。

在這裏插入圖片描述那麼,什麼時候用變色,什麼時候用旋轉呢?

紅黑樹的插入和刪除包含很多種情況,每一種情況都有不同的處理方式.

我們舉一個典型的例子,大家體會一下:

我們以剛纔插入節點21的情況爲例:
在這裏插入圖片描述首先,我們需要做的是變色,把節點25及其下方的節點變色:
在這裏插入圖片描述此時節點17和節點25是連續的兩個紅色節點,那麼把節點17變成黑色節點?恐怕不合適。這樣一來不但打破了規則4,而且根據規則2(根節點是黑色),也不可能把節點13變成紅色節點。

變色已無法解決問題,我們把節點13看做X,把節點17看做Y,像剛纔的示意圖那樣進行左旋轉:

在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述由於根節點必須是黑色節點,所以需要變色,變色結果如下:
在這裏插入圖片描述這樣就結束了嗎?並沒有。因爲其中兩條路徑(17 -> 8 -> 6 -> NIL)的黑色節點個數是4,其他路徑的黑色節點個數是3,不符合規則5。

這時候我們需要把節點13看做X,節點8看做Y,像剛纔的示意圖那樣進行右旋轉:
在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述最後根據規則來進行變色:
在這裏插入圖片描述如此一來,我們的紅黑樹變得重新符合規則。這一個例子的調整過程比較複雜,經歷瞭如下步驟:

變色 -> 左旋轉 -> 變色 -> 右旋轉 -> 變色

三.紅黑樹的應用場景

紅黑樹的應用有很多,其中JDK的集合類TreeMap和TreeSet底層就是紅黑樹實現的.在Java8中,連HashMap也用到了紅黑樹.

幾點說明:

1.關於紅黑樹自平衡的調整,插入和刪除節點的時候都涉及到很多種情況,由於篇幅原因無法展開來一一列舉,有興趣的朋友可以參考維基百科,裏面講的非常清晰。

2.上面紅黑樹調整過程的示例是一種比較複雜的情形,沒太看明白的小夥伴也不必鑽牛角尖,關鍵要懂得紅黑樹自平衡調整的主體思想。

發佈了87 篇原創文章 · 獲贊 39 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章