圖解紅黑樹


圖解紅黑樹

一、紅黑樹的五條規則

紅黑樹除了符合二叉搜索樹的基本規則外,還添加了以下特性:

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

image-20200303121529068

紅黑樹的相對平衡

前面5條規則的約束確保了以下紅黑樹的關鍵特性:

  • 根到葉子節點最長路徑,不會超過最短路徑兩倍
  • 結果就是這棵樹基本是平衡的;
  • 雖然沒有做到絕對的平衡,但是可以保證在最壞的情況下,該樹依然是高效的;

為什么可以做到最長路徑不超過最短路徑的兩倍呢?

  • 性質4決定了路徑上不能有兩個相連的紅色節點;
  • 所以,最長路徑一定是紅色節點和黑色節點交替而成的;
  • 由於根節點和葉子節點都是黑色的,最短路徑可能都是黑色節點,並且最長路徑中一定是黑色節點多於紅色節點;
  • 性質5決定了所有路徑上都有相同數目的黑色節點;
  • 這就表明了沒有路徑能多於其他任何路徑兩倍長。

二、紅黑樹的三種變換

插入一個新節點時,有可能樹不再平衡,可以通過三種方式的變換使樹保持平衡:

  • 變色
  • 左旋轉
  • 右旋轉

2.1.變色

為了重新符合紅黑樹的規則,需要把紅色節點變為黑色,或者把黑色節點變為紅色

插入的新節點通常都是紅色節點

  • 當插入的節點為紅色的時候,大多數情況不違反紅黑樹的任何規則;

  • 插入黑色節點,必然會導致一條路徑上多了一個黑色節點,這是很難調整的;

  • 紅色節點雖然可能導致紅紅相連的情況,但是這種情況可以通過顏色調換和旋轉來調整;

2.2.左旋轉

以節點X為根逆時針旋轉二叉搜索樹,使得父節點原來的位置被自己的右子節點替代,左子節點的位置被父節點替代;

image-20200303132706061

詳解:

如上圖所示,左旋轉之后:

  • 節點X取代了節點a原來的位置;
  • 節點Y取代了節點X原來的位置;
  • 節點X的左子樹 a 仍然是節點X的左子樹(這里X的左子樹只有一個節點,有多個節點時同樣適用,以下同理);
  • 節點Y的右子樹 c 仍然是節點Y的右子樹
  • 節點Y的左子樹 b 向左平移成為了節點X的右子樹

除此之外,二叉搜索樹左旋轉之后仍為二叉搜索樹:

image-20200303132617108

2.3.右旋轉

以節點X為根順時針旋轉二叉搜索樹,使得父節點原來的位置被自己的左子節點替代,右子節點的位置被父節點替代;

image-20200303132529476

詳解:

如上圖所示,右旋轉之后:

  • 節點X取代了節點a原來的位置;
  • 節點Y取代了節點X原來的位置;
  • 節點X的右子樹 a 仍然是節點X的右子樹(這里X的右子樹雖然只有一個節點,但是多個節點時同樣適用,以下同理);
  • 節點Y的左子樹 b 仍然是節點Y的左子樹
  • 節點Y的右子樹 c 向右平移成為了節點X的左子樹

除此之外,二叉搜索樹右旋轉之后仍為二叉搜索樹:

image-20200303132501369

三、紅黑樹的插入操作

首先需要明確,在保證滿足紅黑樹5條規則的情況下,新插入的節點必然是紅色節點

為了方便說明,規定以下四個節點:新插入節點為N(Node),N的父節點為P(Parent),P的兄弟節點為U(Uncle),U的父節點為G(Grandpa),如下圖所示:

image-20200303120344016

3.1.情況1

當插入的新節點N位於樹的根上時,沒有父節點。

這種情況下,只需要將紅色節點變為黑色節點即可滿足規則2 。

image-20200303132357511

3.2.情況2

新界點N的父節點P為黑色節點,此時不需要任何變化。

此時既滿足規則4也滿足規則5。盡管新節點是紅色的,但是新節點N有兩個黑色節點NIL,所以通向它的路徑上黑色節點的個數依然相等,因此滿足規則5 。

image-20200303132304098

3.3.情況3

節點P為紅色,節點U也為紅色,此時節點G必為黑色,即父紅叔紅祖黑

在這種情況下需要:

  • 先將父節點P變為黑色;
  • 再將叔叔節點U變為黑色;
  • 最后將祖父節點G變為紅色;

即變為父黑叔黑祖紅,如下圖所示:

image-20200303132148128

可能出現的問題:

  • N的祖父節點G的父節點也可能是紅色,這就違反了規則4,此時可以通過遞歸調整節點顏色;
  • 當遞歸調整到根節點時就需要旋轉了,如下圖節點A和節點B所示,具體情況后面會介紹;

image-20200303132050765

3.4.情況4

節點P是紅色節點,節點U是黑色節點,並且節點N為節點P的左子節點,此時節點G一定是黑色節點,即父紅叔黑祖黑

在這種情況下需要:

  • 先變色:將父節點P變為黑色,將祖父節點G變為紅色;
  • 后旋轉:以祖父節點G為根進行右旋轉;

image-20200303131956298

3.5.情況5

節點P是紅色節點,節點U是黑色節點,並且節點N為節點P的右子節點,此時節點G一定是黑色節點,即父紅叔黑祖黑

在這種情況下需要:

  • 先以節點P為根進行左旋轉,旋轉后如圖b所示;
  • 隨后將紅色節點P黑色節點B看成一個整體的紅色節點N1,將新插入的紅色節點N看成紅色節點P1 如圖c所示。此時整體就轉換為了情況4。

image-20200303140225631

接着可以按照情況4進行處理:

  • 先變色:將N1節點的父節點P1變為黑色,將祖父節點G變為紅色;

  • 后旋轉:以祖父節點G為根進行右旋轉,旋轉后如圖 e 所示;

  • 最后將節點N1和P1變換回來,完成節點N的插入,如圖 f 所示;

image-20200303131736316

3.6.案例

在二叉樹中依次插入節點:10,9,8,7,6,5,4,3,2,1 。

如果直接采用普通的二叉搜索樹,節點全部插入后是這樣的:

image-20200303161149709

是一個嚴重的不平衡樹,相當於一個鏈表,不能體現出二叉搜索樹的高效率。而按照紅黑樹的五條規則插入節點就能最大程度保證搜索二叉樹是一棵平衡樹。以下為過程詳解:為了方便解釋省略了部分紅黑樹的葉子節點(NIL)

插入10

符合情況1

  • 插入節點10;
  • 將節點10的顏色變為黑色;

image-20200303161257010

插入9

符合情況2

  • 不需要任何變化;

image-20200303161919072

插入8

快速判斷屬於情況3還是情況4的方法:

從新插入的節點N出發,按圖示箭頭經過的四個節點,若為紅紅黑紅3個紅色節點則為情況3,若為紅紅黑黑兩個紅色節點則為情況4;

image-20200303162613413

符合情況4

  • 父節點9變成黑,祖父節點10變為紅;
  • 以祖父節點為根進行右旋轉;

image-20200303163803388

插入7

符合情況3

  • 父節點8和叔節點10變為黑,祖父節點9變為紅;
  • 此時會出現問題:不符合規則2,即根節點不為黑,此時可以把以9為根節點的二叉搜索樹當作一個整體作為一個新插入的節點N,而此時又符合情況1,只需要把9變回黑色即可。

image-20200303165135028

插入6

符合情況4

  • 父節點7變為黑,祖父節點8變為紅;
  • 以祖父節點8為根進行右旋轉;

image-20200306170016958

插入5

符合情況3

  • 父節點6和叔節點8變為黑,祖父節點7變為紅;

image-20200303170150314

插入4

符合情況4

  • 父節點5變為黑,祖父節點6變為紅;
  • 以祖父節點6為根進行右旋轉;

image-20200303171028009

插入3

第一次變換:符合情況3

  • 父節點4和叔節點6變為黑,祖父節點5變為紅;

變換之后發現5和7為相連的兩個紅色節點,於是把以5為根的整個子樹看成一個新插入的節點N1,再進行第二次變換。

image-20200303171755035

第二次變換:符合情況4

  • 父節點7變為黑,祖父節點9變為紅;
  • 以祖父節點9為根進行右旋轉;

image-20200303172800302

最后復原N1得到變換后的紅黑樹:

image-20200303173158141

插入2

符合情況4

  • 父節點3變為黑,祖父節點4變為紅;
  • 以祖父節點4為根進行右旋轉;

image-20200303174011409

插入1

第一次變換:符合情況3

  • 父節點2和叔節點4變為黑,祖父節點3變為紅;

變換之后發現3和5為相連的兩個紅色節點,於是把以3為根的整個子樹看成一個新插入的節點N1,再進行第二次變換。

image-20200303180603741

第二次變換:符合情況3

  • 父節點5和叔節點9變為黑,祖父節點7變為紅;即由圖 b -> 圖 c 。

變換之后發現根節點7為紅色不符合規則2,所以把以7為根節點的紅黑樹看成一個新插入的節點N2,再進行第三次變換。

第三次變換:符合情況1

  • 直接將根節點7變為黑色即可。

image-20200303181133397

由此,完成了1~10節點的插入,雖然沒有遇到情況5,不過情況5經過左旋轉的操作便可轉換為情況4,原理一樣。如下圖所示,將這棵紅黑樹的葉子節點NIL補全之后,經檢驗滿足紅黑樹的五條規則,並且基本屬於平衡樹,效率較高。

image-20200303182326442

四、紅黑樹的刪除操作

紅黑樹的刪除操作結合了復雜的二叉樹的刪除操作和復雜的紅黑樹的插入規則,整體來說難度非常大,篇幅較長,這里暫不進行探討。

參考資料:JavaScript數據結構與算法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM