紅黑樹,看不懂你找我

一:什麼是紅黑樹

紅黑樹是AVL樹的一種流行變種,是具有以下五個特點的二叉查找樹

  1. 每一個節點或者着成紅色,或者着成黑色
  2. 根是黑色
  3. 每個葉節點Nil是黑色
  4. 如果一個節點是紅色的,那麼它的子節點必須是黑色的
  5. 每一條從某節點到某Nil指針的路徑必須包含相同數目的黑色節點

二:關於紅黑樹的一般操作

對紅黑樹操作,最困難的就是保持上述的紅黑樹性質中的紅色標記部分。

1.查找操作

紅黑樹是二叉查找樹,所以其查找操作與一般的二叉查找樹相同

  • 令根節點爲當前節點
  • 當前節點爲Nil,返回Nil
  • 要找的值等於當前節點,返回當前節點
  • 要找的值大於當前節點, 令右兒子爲當前節點,重複步驟2
  • 要找的值小於當前節點,令左兒子爲當前節點,重複步驟2

操作的時間複雜度O(logN)

2. 插入操作

當我們想向樹中插入一個新節點時,通常把這個節點作爲葉節點插入。

Part1:
假設把這個點塗成黑色,那完了,肯定違反了條件5,因爲本來任意的節點到某Nil指針的路徑中黑色節點數是相同的,現在加上黑色節點的這條路徑黑色節點數度肯定會+1,於是原來的條件被破壞了,因此,新加的節點必須被塗成紅色

Part2:
如果新插入的節點的父節點是黑色的,那麼直接插入新的紅節點就完事了

Part3:
如果新插入的節點的父節點是紅色,那麼條件4就被破壞了,這種情況下,我們必須在保持條件5不被破壞的同時,利用改變節點顏色以及樹的旋轉來滿足所有條件。

2.1 新節點:我是紅色的,我爹是紅色的,我叔叔是黑色的

在這裏插入圖片描述

  • 設置P爲黑色
  • 設置G爲紅色
  • 進行右單旋轉

在這裏插入圖片描述

  • 設置X爲黑色
  • 設置G爲紅色
  • 進行右雙旋轉

還有對稱的兩種情況,操作也是對稱的

2.2 新節點:我是紅色的,我爹是紅色的,我叔叔也是紅色的

在這裏插入圖片描述

  • 把G節點設置爲紅色
  • 把P節點設置爲黑色
  • 把S節點設置爲黑色
    在這裏插入圖片描述
  • 把G節點設置爲紅色
  • 把P節點設置爲黑色
  • 把S節點設置爲黑色

這時候,如果G的父節點也是紅的,那麼G的顏色翻轉的操作就會影響性質4,於是我們對G節點以及其父節點GP和父節點的兄弟節點GPS進行2.1所示的旋轉操作

注意如果G的父節點GP爲紅色,G父節點的兄弟節點GPS肯定不能爲紅色,只能爲黑色,因爲在紅黑樹中,不可能出現出現深度小於樹的總深度且雙兄弟都爲紅的情況,這種情況在其他的插入或刪除過程中已經消除了。
在這裏插入圖片描述

GP剛好爲根結點時,那麼根據性質2,我們必須把GP重新設爲黑色,那麼樹的紅黑結構變爲:黑黑紅。換句話說,從根結點到葉子結點的路徑中,黑色結點增加了。這也是唯一一種會增加紅黑樹黑色結點層數的插入情景。

還有對稱的兩種情況,操作也是對稱的

難點來了,難點來了!!


其實不難

3.刪除操作

刪除操作一直一來是樹這種ADT的難點所在

一般二叉搜索樹的刪除操作:

  • 該節點爲葉節點的情況:可以直接刪除,將其父節點的兒子指針設爲Nil
  • 該節點只有一個非空子節點:可以直接刪除,將其父節點的兒子指針指向其唯一兒子
  • 該節點有兩個非空子節點:用該節點左子樹的最大節點或者右子樹的最小節點替換該節點,然後刪除對應的左子樹最大節點或者右子樹最小節點,最終可以回到前兩種情況。

好,到這裏你肯定還是明白的對吧

現在考慮紅黑樹的刪除操作。

注意:
根據一般二叉搜索樹的刪除操作來看,我們要刪除的節點其實不一定是最終從圖中移出去的節點,稱最終從圖中移出去的節點爲替代點,我們先從右子樹的最小節點(或左子樹的最大節點)找到我們的替代點,與刪除點的值交換,但是顏色都不變,然後再刪除替代點,然後對樹的性質進行恢復。而現在這些替代點都是一些樹的末節點(區別於葉節點,我們現在將Nil節點視爲黑色葉節點),刪除操作便會簡化許多,並可以歸納爲像插入那樣的幾個類別。當然了替代點和我們要刪除的點也有可能是同一點,但處理方法是一樣的。

我們雖然刪除了替代點,但是我們對樹進行恢復時,還是會將該替代點放在樹中參與恢復,恢復完成後再移掉。

在本文中,示例都默認是選擇右子樹的最小節點作爲真正刪除點,也可以選擇左子樹的最大節點

在這裏插入圖片描述

3.1替代點是紅色的

直接從樹中去掉即可,不會影響紅黑樹的性質,算法直接結束

不會出現替代點爲紅色且有兒子爲非葉子節點的情況,所以這種情況是最簡單的
在這裏插入圖片描述

3.2替代點是黑色的

替代點是黑色,那麼刪除之後樹的性質就被破壞了,需要進行修復

3.2.1 有一個兒子爲且必須爲紅色時

當替代節點只有一個兒子且爲紅色時
直接用它的紅色兒子節點取代它,並將顏色改爲黑色,這樣所有經過替代節點的路徑都將經過他的兒子,黑色高度不變。

在這裏插入圖片描述
注意這跟上面圖不一樣,這張圖D節點是替代節點

不可能存在只有一個兒子且兒子爲黑色的情況,那樣本身就是不平衡的

3.2.2 有兩個黑色兒子

當替代點是黑色的且有兩個黑色兒子(可以爲葉節點Nil)時,那他肯定有兄弟,那麼又可以分爲其他幾類

  • 替代點是黑色,其兄弟節點是紅色
  • 替代點是黑色,其兄弟節點是黑色
3.2.2.1 替代點的兄弟節點是紅色

在這裏插入圖片描述

  • 將G節點也就是替代點的父節點設置爲紅色,
  • 兄弟節點S設置爲黑色
  • 然後進行向左單旋轉,

現在可以直接刪掉D了嗎?(以下都默認標識D爲替代點) tan90°\hspace4ex 不行,tan90\degree

這個操作不改變任何路徑的黑色高度,這時候刪去D肯定會變的不平衡,我們只是把情況變爲了兄弟節點爲黑色的情況,也就是下面將要敘述的情況,我們接下來需要重新進入算法,進一步處理

3.2.2.2 替代點的兄弟節點是黑色

替代點D與其兄弟節點S都是黑色的,所以D的父節點顏色是不確定的,用綠色表示

又分爲以下幾種情況

3.2.2.2.1 當兄弟節點的兩個兒子也都是黑色

在這裏插入圖片描述
PS:C1、C2可爲Nil

  • S節點顏色變爲紅
  • G節點顏色變黑
  • 把G作爲新的替代點進行下一輪操作

假設G一開始是黑色的,這個操作過後,所有一開始經過S節點的路徑黑色高度-1,那麼在刪除D節點後,所有經過D節點的路徑黑色高度也會-1,這棵子樹大家黑色高度都減一,結局竟該死的甜美,但是經過G的比不經過G的黑色高度減一了,所以再在G上重新平衡處理

假設G一開始是紅色的,這個操作後,所有一開始經過S節點的路徑黑色高度不變,經過D的路徑黑色高度+1,那麼在刪除D後,所有經過D節點的路徑黑色高度又變回來了,結局竟還是該死的甜美,經過G爲根的子樹已經平衡了,再在G上重新平衡處理

注意當G是樹的根時,就表示我們已經做完了,我們從所有路徑去除了一個黑色節點,所有性質在上溯過程中都保持着。

3.2.2.2.2 當兄弟節點的左兒子是紅色的,右兒子是黑色

在這裏插入圖片描述

  • C1設置爲黑色
  • S設置爲紅色
  • 對S進行向右單旋轉

這樣的操作不改變任何路徑的黑色高度,本來的平衡狀態不變,所以刪除D之後就破壞了原先的條件,還要進行自平衡變換,此時成了下面一種情況繼續處理

3.2.2.2.3 當兄弟節點的右兒子是紅色的,左兒子隨意

在這裏插入圖片描述

  • 交換G和S的顏色
  • 設置兄弟節點的右兒子C2爲黑色
  • 進行向左單旋轉

該操作使所有變化前經過S節點的路徑黑色高度都不變,經過D的路徑黑色高度+1,在刪除D後,所有經過G節點的路徑都不變,達到平衡

說白了刪除就是不斷遞歸變換直到滿足替代點的刪除條件。

例子:刪除30根節點
在這裏插入圖片描述

在這裏插入圖片描述
練習一下吧,這裏有個在線紅黑樹工具,戳

三:漸進邊界的證明

包含n個內部節點的紅黑樹的高度是O(logn)O(logn)

定義:

h(v)v{\displaystyle h(v)}表示以節點{\displaystyle v}爲根的子樹的高度。
bh(v)v{\displaystyle bh(v)}表示從{\displaystyle v}到子樹中任何葉子的黑色節點的數目
v(如果{\displaystyle v}是黑色則不計數它,也叫做黑色高度)。

v2bh(v)1引理:以節點{\displaystyle v}爲根的子樹有至少2^{bh(v)}-1個內部節點。
引理的證明(通過歸納高度):

歸納假設:
vNILbh(v)=0bh(v)=02bh(v)1=201=0如果v的高度是零則它必定是NIL,因此{\displaystyle bh(v)=0}{\displaystyle bh(v)=0}。所以:2^{{bh(v)}}-1=2^{{0}}-1=0

h(v)=k2bh(v)1如果h(v)=k,有2^{bh(v)}-1個內部節點成立
h(v)=k+1於是h(v')=k+1
vh(v)>0bh(v)bh(v)1v2bh(v)11v因爲v'有h(v')>0 \\所以它是個內部節點。同樣的它有的兩個兒子,其黑色高度要麼是bh(v')要麼是bh(v')-1(依據v'是紅色還是黑色)。通過歸納假設每個兒子都有至少2^{{bh(v')-1}}-1個內部接點,所以v'有:
2bh(v)11+2bh(v)11+1=2bh(v)12^{bh(v')-1}-1+2^{bh(v')-1}-1+1=2^{bh(v')}-1個內部節點。

使(4)h(root)2使用這個引理我們現在可以展示出樹的高度是對數性的。\\ 因爲在從根到葉子的任何路徑上至少有一半的節點是黑色(根據紅黑樹性質4),\\根的黑色高度至少是 {\frac {h(root)}{2}}通過引理我們得到:

n2h(root)21  log(n+1)h(root)2  h(root)2log(n+1)n2h(root)21  log(n+1)h(root)2  h(root)2log(n+1){\displaystyle n\geqslant 2^{\frac {h(root)}{2}}-1\leftrightarrow \;\log {(n+1)}\geqslant {\frac {h(root)}{2}}\leftrightarrow \;h(root)\leqslant 2\log {(n+1)}}n\geqslant 2^{{{\frac {h(root)}{2}}}}-1\leftrightarrow \;\log {(n+1)}\geqslant {\frac {h(root)}{2}}\leftrightarrow \;h(root)\leqslant 2\log {(n+1)}

O(logn)因此根的高度是{\displaystyle {\text{O}}(\log n)}

在這裏插入圖片描述

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