圖解紅黑樹

圖解紅黑樹

1、紅黑樹的五條規則

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

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

image-20200303121529068

紅黑樹的相對平衡數據結構

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

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

爲何能夠作到最長路徑不超過最短路徑的兩倍呢?遞歸

  • 性質4決定了路徑上不能有兩個相連的紅色節點;
  • 因此,最長路徑必定是紅色節點和黑色節點交替而成的;
  • 因爲根節點和葉子節點都是黑色的,最短路徑可能都是黑色節點,而且最長路徑中必定是黑色節點多於紅色節點;
  • 性質5決定了全部路徑上都有相同數目的黑色節點;
  • 這就代表了沒有路徑能多於其餘任何路徑兩倍長。

2、紅黑樹的三種變換

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

  • 變色
  • 左旋轉
  • 右旋轉

2.1.變色

爲了從新符合紅黑樹的規則,須要把紅色節點變爲黑色,或者把黑色節點變爲紅色v8

插入的新節點一般都是紅色節點get

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

  • 插入黑色節點,必然會致使一條路徑上多了一個黑色節點,這是很難調整的;
  • 紅色節點雖然可能致使紅紅相連的狀況,可是這種狀況能夠經過顏色調換和旋轉來調整;原理

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

3、紅黑樹的插入操做

首先須要明確,在保證知足紅黑樹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

4、紅黑樹的刪除操做

紅黑樹的刪除操做結合了複雜的二叉樹的刪除操做和複雜的紅黑樹的插入規則,總體來講難度很是大,篇幅較長,這裏暫不進行探討。

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

相關文章
相關標籤/搜索