紅黑樹簡介及左旋、右旋、變色

紅黑樹簡介及左旋、右旋、變色

紅黑樹(Red Black Tree)是一種自平衡二叉搜索樹(二叉查找樹),是一種特殊的二叉搜索樹,在進行插入和刪除操作時通過特定操作保持二叉搜索樹的平衡,從而獲得較高的查找性能。

紅黑樹的平衡操作通過左旋、右旋和變色來實現,平衡的過程是比較複雜的,但通過平衡操作,可以獲得更高效的性能。對二叉搜索樹進行平衡後,最壞情況的運行時間得到優化,可以在O(logN)的時間複雜度內完成查找、插入和刪除,N是二叉搜索樹中的節點數。

一、二叉搜索樹的性能分析

紅黑樹是一種特殊的二叉搜索樹,所以本文先從二叉搜索樹說起。

二叉搜索樹是一種特殊的二叉樹,具有如下特性:

1. 如果二叉樹的左子樹不爲空,則左子樹上所有節點的值均小於它的根節點的值。

2. 如果二叉樹的右子樹不爲空,則右子樹上所有節點的值均大於它的根節點的值。

3. 如果獨立地看,左子樹、右子樹也分別爲二叉搜索樹。

關於二叉搜索樹的實現,可以參考:https://blog.csdn.net/weixin_43790276/article/details/105753543

向二叉搜索樹中插入數據時,爲了滿足二叉搜索樹的特性,會遞歸地比較插入節點的值與根節點的值,將數據插入正確的位置。

如在一棵空二叉搜索樹中插入 [50, 77, 55, 29, 10, 30, 66, 80, 51, 18, 90] ,得到的二叉搜索樹結構如下圖:

從結構圖可以看出,這棵二叉搜索樹是平衡的,當在二叉搜索樹中查找數據時,按照二分法查找的思想,從根節點開始,然後到子樹中進行查找,如果沒有查找到目標數據,每次都會往樹的下一層進行查找,需要的最大查找次數等於樹的深度。最壞的情況就是找到樹的最深一層,所以在這棵樹中查找的最壞情況是查找4次。

還是上面例子中的數據,假設比根節點50大的數據是升序排列的,如 [50, 51, 55, 66, 77, 80, 90, 29, 10, 30, 18] ,比根節點50小的數據順序不變,將這些數據插入到二叉搜索樹中,得到的二叉搜索樹結構如下圖:

很明顯,這棵二叉搜索樹是不平衡的。在這棵樹中查找數據的最壞情況需要查找7次,查找次數多的原因就是樹的不平衡,右子樹一直在往深度上延伸。如果把根節點和右子樹拿出來,結構如下圖:

 

根據結構圖,這是一棵右斜樹。它雖然是一棵二叉樹,但它更像是一個鏈表,正在向鏈表“退化”。鏈表的時間複雜度是O(N),平衡二叉樹的時間複雜度是O(logN),當N很大的時候,O(N)與O(logN)的性能差距是很大的。

可見,二叉搜索樹的插入順序會影響到樹的結構,從而影響性能。對於上面的例子,總共只有11個節點,出現7個數據順序排列的可能性不大,但在實際的應用場景中,節點可能是110個,11000個,11000000個,甚至更多。在數據量增大的時候,這些數據中出現一段或多段數據順序排列的可能性是很大的,這就會造成二叉搜索樹極度不平衡,向鏈表退化,性能大大降低。

所以,保持二叉搜索樹的平衡,對性能的保證有至關重要的作用。由於數據是動態變化的,會動態地增加或減少,所以不可能在構造二叉搜索樹前控制數據的排列順序。要保持二叉搜索樹的平衡,就要在每增加一個節點或每減少一個節點時都保持平衡,即讓二叉搜索樹一直保持平衡,這樣二叉搜索樹的性能就不可能向鏈表退化。

當二叉搜索樹中的節點數量發生改變時,使用一些策略來保持平衡,紅黑樹就是這樣一種二叉樹。

二、紅黑樹簡介

紅黑樹是一種自平衡二叉搜索樹,每個節點都有顏色,顏色爲紅色或黑色,紅黑樹由此得名。除了滿足二叉搜索樹的特性以外,紅黑樹還具有如下特性:

1. 節點是紅色或黑色。

2. 根節點是黑色。

3. 所有葉子節點都是黑色的空節點。(葉子節點是NIL節點或NULL節點)

4. 每個紅色節點的兩個子節點都是黑色節點。(從每個葉子節點到根的所有路徑上不能有兩個連續的紅色節點)

5. 從任一節點到其每個葉子節點的所有路徑都包含相同數目的黑色節點。

要知道什麼是紅黑樹,必須記住這5條特性。這5條特性其實是5條規定,只有滿足這5條規定才屬於紅黑樹。對於二叉搜索樹的特性,只要理解了,很容易記住,但對於紅黑樹的5條特性,需要“死記硬背”。

如上面例子中的二叉搜索樹,可以加上顏色變成一顆紅黑樹。(實際的紅黑樹是一個節點一個節點插入的,如下的構造過程只是爲了先理解紅黑樹的5條特性)

1. 先加上葉子節點,並把所有節點都標記爲黑色。

2. 這棵二叉樹顯然不滿足紅黑樹的特性5,如節點10到左子樹的葉子節點的路徑上有一個黑節點,到右子樹的葉子節點的路徑上有兩個黑節點,所以要將一些黑節點變成紅節點。

從根節點50開始,使根節點到每個葉子節點的路徑上都有4個黑節點,得到的紅黑樹如下。

當然,也可以使根節點到每個葉子節點的路徑上都有3個黑節點,得到的紅黑樹如下。

現在看一下這兩棵樹是否滿足紅黑樹的5條特性,可以一條一條的對比,至於構造的過程先不管(這其實是硬拼出來的),後面再講怎麼構造。

根據紅黑樹的特性5,任意節點到其所有葉節點的路徑上的黑節點數都相同,從而保持紅黑樹的平衡。如果只看黑節點,這種平衡是完美的平衡,所以紅黑樹的平衡也稱爲黑色完美平衡。當然,因爲紅節點的存在,紅黑樹並不是完美平衡的,甚至有可能不滿足平衡二叉樹的特性。

當在紅黑樹中插入節點或刪除節點時,紅黑樹的平衡很可能會被破壞(不滿足其中一條或多條特性),要立即對紅黑樹進行調整,使紅黑樹重新滿足5條特性。

調整平衡的操作包含左旋、右旋和變色,下面依次對這些操作進行介紹。

三、紅黑樹的左旋和右旋操作

對於一棵紅黑樹,它滿足紅黑樹的5條特性。插入或刪除節點之後,紅黑樹就發生了變化,很可能不再完全滿足紅黑樹的5條特性了,也就是不再是一棵紅黑樹了,而是一棵普通的二叉搜索樹。這時候,爲了使二叉搜索樹重新變成紅黑樹,就需要對二叉搜索樹進行操作,使它滿足紅黑樹的5條特性。

通過旋轉,可以使二叉搜索樹重新滿足紅黑樹的5條特性。旋轉分爲左旋和右旋。

1. 紅黑樹的左旋

左旋:以某個節點作爲支點(旋轉節點),其右子節點變爲旋轉節點的父節點,右子節點的左子節點變爲旋轉節點的右子節點,旋轉節點的左子節點保持不變。右子節點的左子節點相當於從右子節點上“斷開”,重新連接到旋轉節點上。

爲了不失一般性,可以看下圖中的例子。左邊是左旋前的紅黑樹局部結構,先不考慮整體,只看局部,左旋前不滿足紅黑樹的特性5。

左旋時,旋轉節點爲節點50,左旋後,旋轉節點的右子節點70變爲旋轉節點50的父節點,右子節點的左子節點60從右子節點70上“斷開”,成爲旋轉節點50的右子節點。

左旋後,結構如右圖,這個局部重新滿足了紅黑樹的特性5,達到目的。

再看另一個左旋的例子,左邊是左旋前的局部結構,以節點10作爲旋轉節點,左旋後,旋轉節點的右子節點20成爲旋轉節點10的父節點,右子節點的左子節點(這裏是一個葉子節點NIL)從右子節點上“斷開”,成爲旋轉節點10的右子節點。

2. 紅黑樹的右旋

右旋:以某個節點作爲支點(旋轉節點),其左子節點變爲旋轉節點的父節點,左子節點的右子節點變爲旋轉節點的左子節點,旋轉節點的右子節點保持不變。左子節點的右子節點相當於從左子節點上“斷開”,重新連接到旋轉節點上。

不難看出,左旋和右旋是相反的,可逆的。

下圖中的例子仍然是紅黑樹的局部,左邊的結構不滿足紅黑樹的特性5。

右旋時,旋轉節點爲節點70,右旋後,旋轉節點的左子節點50變爲旋轉節點70的父節點,左子節點的右子節點60從左子節點50上“斷開”,成爲旋轉節點70的左子節點。右旋後(右圖),重新滿足了紅黑樹的特性5。

同樣再看一個右旋的例子,左邊是右旋前的局部結構,以節點30作爲旋轉節點,右旋後,旋轉節點的左子節點20成爲旋轉節點30的父節點,左子節點的右子節點(這裏是一個葉子節點NIL)從左子節點上“斷開”,成爲旋轉節點30的左子節點。

通過對左旋和右旋的介紹和舉例,左旋和右旋的目的都是通過旋轉節點的方式使二叉搜索樹重新滿足紅黑樹的特性,左旋和右旋是互逆的,根據不同的情況使用不同的旋轉方式。

四、紅黑樹的變色操作

當對紅黑樹進行插入或刪除節點之後,如果不再完全滿足紅黑樹的5條特性,除了旋轉,變色也可以使二叉搜索樹重新滿足紅黑樹的5條特性。

變色:將節點的顏色由紅變黑或由黑變紅。

向紅黑樹中插入節點時,新節點的顏色都設置爲紅色。不管新節點是什麼顏色,特性3都不可能被破壞,特性1、2、4都有可能被破壞。如果插入的節點是黑色,則一定會破壞特性5,需要進行調整,如果插入的節點是紅色,則一定不會破壞特性5。所以將新節點設置爲紅色,可以降低破壞紅黑樹特性的可能性。

1. 添加節點

如下的左圖是紅黑樹的一個局部,一開始是滿足紅黑樹的特性的,在其中插入了紅色節點10,兩個紅節點連在一起了,不再滿足紅黑樹的特性4。

通過變色,先將節點20變成黑色,特性4滿足了,但又不滿足特性5,所以繼續將節點30變成紅色,節點40變成黑色。

經過3次變色後,從局部看,已經重新滿足了紅黑樹的特性。但是,從整棵樹來看,還不一定滿足紅黑樹的特性,如果節點30的父節點也是紅色,則還需要繼續對這棵樹進行調整(上面的左旋和右旋例子中也有這種情況)。

2. 刪除節點

如下的左圖是紅黑樹的一個局部,一開始是滿足紅黑樹的特性的,將節點90刪除後,不再滿足紅黑樹的特性5。

通過變色,先將節點80變成黑色,但仍不滿足特性5,繼續將節點70變成紅色,重新滿足了紅黑樹的特性。

經過兩次變色,重新滿足了紅黑樹的特性,對於這個例子,只要局部滿足了,整棵樹一定是滿足紅黑樹的。

五、紅黑樹的旋轉和變色綜合案例

上文中介紹旋轉和變色時,是獨立對它們進行分析的。這兩種調整方法都可以使被破壞規則的紅黑樹重新滿足紅黑樹的特性,更多的時候,需要靈活地配合使用,使調整更高效。

下面來看一個簡單的例子。使用文章開頭的紅黑樹,結構如下圖。

1. 在紅黑樹中插入節點20,插入後不滿足紅黑樹的特性4。

2. 將節點18從紅色變成黑色,變色後不滿足紅黑樹的特性5。

3. 以節點18作爲旋轉節點,進行左旋,左旋後還是不滿紅黑樹的特性5。

4. 將節點10從黑色變成紅色,變色後,重新滿足了紅黑樹的5條特性。

經過變色,左旋,變色,三個步驟之後,插入節點後的樹重新成爲一棵紅黑樹。

本文中舉例的結構圖是爲了方便理解紅黑樹以及紅黑樹的旋轉和變色,一棵真正的紅黑樹是一個節點一個節點地插入而得到的,並一定能得到上面圖形裏的這些結構。對於紅黑樹的插入、刪除和代碼實現,本專欄的其他文章會繼續介紹。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章