文章目錄
一:什麼是紅黑樹
紅黑樹是AVL樹的一種流行變種,是具有以下五個特點的二叉查找樹:
- 每一個節點或者着成紅色,或者着成黑色
- 根是黑色
- 每個葉節點Nil是黑色
- 如果一個節點是紅色的,那麼它的子節點必須是黑色的
- 每一條從某節點到某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爲替代點)
這個操作不改變任何路徑的黑色高度,這時候刪去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個內部節點的紅黑樹的高度是
定義: