紅黑樹(3) - 刪除操做

在本系列的前面兩篇文章中。已經介紹了紅黑樹以及其插入操做。

詳細可參考如下兩個連接:
紅黑樹(1) - 介紹
紅黑樹(2) - 插入操做
spa

1.刪除操做介紹

相似於插入操做。紅黑樹進行刪除節點時,也使用又一次着色以及旋轉這兩種方式。來維護它的屬性。在插入操做中,咱們主要是依靠檢測叔節點的顏色來決定哪一種場景。在刪除操做中,咱們使用檢測兄弟的顏色,來決定是哪一種場景。


在插入操做中,最多見的違反紅黑樹屬性的一種狀況是存在兩個連續的紅色節點。.net

而在刪除操做中。常見的狀況是,當刪除節點是黑色時,會影響從根節點到葉子的黑色節點高度。違反紅黑樹的性質5。blog


刪除的過程相對照較複雜。爲了便於理解刪除過程,咱們將使用到"double black"的概念。當一個黑色節點被刪除,並且被它的黑色孩子代替時,這個孩子就標記爲double black。所以,基本的工做就變爲了將這個double black轉換爲single black。
ci

2.刪除操做步驟

如下是具體的刪除步驟。

在如下的內容裏。d表示被刪節點。c表示將用於替換d的孩子節點get

運行標準的二叉搜索樹的刪除操做。在刪除過程當中,假設d是葉子或者僅僅有一個孩子。則操做比較簡單,基本上直接刪除就可以了。而對於存在兩個孩子的節點,可以先查找到d的中序遍歷時的後繼節點。用它的值替換掉d的值,而後再刪除這個後繼節點(中序遍歷時的興許節點老是一個葉子或僅僅有一個孩子)。

例如如下圖所看到的。這種話。咱們僅僅需要處理被刪節點是葉子或僅僅有一個孩子的這種狀況。class

              50                                            60                                        60
           /     \           delete(50)               /   \          delete(60')           /  \
        40     70    ----------------->      40    70 ------------------>   40   70
                 /  \      後繼節點賦值                  /  \      刪除後繼節點               \
              60   80   給被刪節點                  60'   80                                      80 
上圖中,被刪節點d是50,則它的中序遍歷後繼節點是60。用後繼節點的值替換d的值,而後刪除60這個後繼節點。
固然,在本步驟中,也可以選取前驅節點(即被刪節點左子樹最大值)進行替換。

原理與後繼節點類似。這裏再也不描寫敘述。原理

3. 簡單場景-d或者c是紅色

使用孩子節點c替換d。而後將其置爲黑色。這樣黑色高度維持不變。這是因爲d和c不可能同一時候是紅色。當中必然有一個爲黑色。
本步驟會覆蓋到如下的這4種場景。

              30                            30
           /     \       delete(20)        /   \
          20      40    ------------->    10    40 
         /                                  
        10                          
              30                            30
           /     \       delete(10)        /   \
          10      40    ------------->    20    40 
            \                               
            20         
              30                            30
           /     \       delete(20)        /   \
          20      40    ------------->    10    40 
         /                                  
        10        
              30                            30
           /     \       delete(10)        /   \
          10      40    ------------->    20    40 
            \                                  
            20  
對於d擁有兩個孩子(兩顆子樹)的場景。如如下的兩個圖所看到的。可以採用第2節提供的方法。轉換爲處理葉子節點或單個孩子的場景。
              40                                 40                                40
           /     \        delete(20)           /   \        delete(30')           /  \
          20      50 ---------------------->  30    50 --------------------->   30   50
         /  \          運行步驟2.1,將d的       /  \      此時轉換爲了刪除葉子30'.   /
        10  30         後繼節點的值賦給d.      10  30'                           10
              40                                 40                                40
           /     \        delete(20)           /   \        delete(30')           /  \
          20      50 ---------------------->  30    50 --------------------->   30   50
         /  \          運行步驟2.1,將d的       /  \      此時轉換爲了刪除葉子30'.   /
        10  30         後繼節點的值賦給d.      10  30'                           10

4. 複雜場景-d和c都是黑色(包含d是葉子)

4.1. 孩子節點c是double black

此時,主要工做就是將這個double black轉換爲single black。注意:當d是葉子時,則默認c爲null節點並且爲黑色。

因此,假設刪除的是黑色葉子,則也會引起double black操做。二叉樹


上圖中,在轉換爲了double black後,實際上已經變成了4.2.1.c的場景。可以使用Right Right Case旋轉方式。
終於,刪除節點20後,這棵樹調整爲:
              30                            40
           /     \       delete(20)        /   \
          20      40    ------------->    30    50 
                    \                             
                     50               

4.2. d是double black。或者d不是根節點

在這樣的狀況下,若是s表示d的兄弟節點,則存在如下這些場景。

4.2.1. s是黑色,並且s的孩子中至少有一個是紅色。則進行旋轉

若是s的這個紅色的孩子爲r,則依據s和r的位置,可以分爲4種狀況。

a. Left Left Case (s是左孩子,且r是s的左孩子或者s的兩個孩子都是紅色)。搜索

這樣的情形與如下的Right Right Case正好相反。遍歷

b. Left Right Case (s是左孩子,且r是s的右孩子)。這樣的情形與如下的Right Left Case正好相反。

c. Right Right Case (s是右孩子,且r是s的右孩子或者s的兩個孩子都是紅色)。


d. Right Left Case (s是右孩子,且r是s的左孩子)。



4.2.2. s是黑色,並且s的兩個孩子都是黑色(包含s是葉子)

這樣的狀況下需要又一次着色。並且:
a. 假設s的父節點是黑色,則作完刪除操做後,還需要檢測父節點。


b. 假設s的父節點是紅色,則不需要再檢測父節點,而是可以簡單地將其設置爲黑色(紅色+double black = single black)。

4.2.3. s是紅色,運行旋轉操做,提高s。並且又一次着色s以及它的父節點

此時新的兄弟節點老是黑色的(下圖的節點25)。至此,已經將這棵樹經過旋轉,轉換爲了兄弟爲黑色的這樣的場景。使用4.2.1或者4.2.2繼續處理。這樣的情形可以分爲兩種狀況。
a. Left Case (s是左孩子)。右旋轉父節點p。
b. Right Case (s是右孩子). 左旋轉父節點p。



4.3. 假設c是根節點,將其轉換爲single black而後返回(全然二叉樹的黑色高度減1).

相關文章
相關標籤/搜索