紅黑樹刪除操作


若被刪除的結點有兩個非葉子結點,那么可以轉換為刪除一個“替代點”的問題,該替代點最多只有一個非葉子孩子結點。可以通過前驅或者后繼(都最多有一個非葉子孩子結點)來替代最初要被刪除的結點,所以下面只關注只有一個非葉子孩子結點的問題,一旦我們解決了這個問題,那么解決方法將同樣適用於兩種情形:
1、原本想刪除的結點最多有一個非葉子孩子結點
2、原本想刪除的結點有兩個非葉子孩子結點(通過前驅和后繼可以轉化為最多有一個非葉子孩子結點)

好了,現在用N來表示替代結點(要是被刪除的結點沒有替代結點,那么N就表示原本要被刪除的結點,由紅黑樹的屬性可以推出該結點不可能有孫子結點),替代結點要么是前驅,要么是后繼,但是都最多只有一個非葉子孩子結點(程序中使用的是前驅)。結點N為不同顏色時,處理方式不一樣,具體如下。

結點N為紅色:

若結點N為紅色,那么它的孩子結點必須是黑色的,而且兩個孩子結點都是葉子結點(因為結點N最多只能有一個非葉子孩子結點,所以只能是一邊是一個黑色的非葉子孩子結點,另一邊是一個黑色葉子結點,這樣通過結點N的路徑的黑色結點的數目就不一樣了(因為黑色的非葉子孩子結點至少有兩個黑色葉子結點),這樣就違反了性質5)。此時直接將N刪除即可,刪除之后N被空葉子結點(NULL)替代,而NULL結點都是黑色的,所以屬性5依然保持。好了,結點N為紅色的情形比較簡單,下面看結點N為黑色的情形。

結點N為黑色:

結點N為黑色時,可以分為兩種情況:
第1種情況:若其孩子結點M有一個是非葉子結點,另外一個是黑色空葉子結點,那么非葉子結點M必須是紅色。因為如果非葉子結點也是黑色的,這樣通過結點N的路徑的黑色結點的數目將不一樣(通過空葉子結點這邊的黑色結點的數目是2,而通過黑色非葉子結點這邊的至少是3),由此違反了性質5。所以非葉子結點M只能是紅色的,這種情況比較簡單,只需用M代替N,並將M變為黑色,則不違反任何屬性,此時依然是一棵合格的紅黑樹。

第2種情況:若兩個孩子結點都為空葉子結點(葉子結點都為黑色,並且是NULL),則此時用空葉子結點NULL替代N后,通過原始替代結點N的路徑的黑色結點的數目將比原來減少1,此時就要分類討論了,將替代結點N的父結點表示為P,兄弟結點表示為S。具體分類如下:

case 1:

N是根結點,在這種情況下,我們已經做完了(僅僅通過直接返回就可以達到這個效果!),因為這種情況下整棵樹只有一個結點(注意大前提:N的兩個孩子結點都是空葉子結點,所以整棵樹只有一個結點),要刪除的結點正是根結點,直接返回之后,在上一層函數中用N的子結點(NULL)替代N,相當於將N刪除掉了。

#294#_     
     |     
     ~317~ 

Deleting key 1th: 294 ---------------------------------------------------------------------

case 0 <294> (若當前結點的子結點為紅色,則將子結點變成黑色) : 
#294#_     
     |     
     #317# 

case 0 <294> (將當前結點用子結點替代,之后釋放當前結點) : 
#317# 

Deleting key 1th: 317 ---------------------------------------------------------------------

case 1 <317> (若當前結點是根結點,直接返回) : 
case 0 <317> (將當前結點用子結點替代,之后釋放當前結點) : 
NODE is NULL

 



注意:在case 2,case 5,case 6中,我們假設N是父結點P的左孩子結點,如果是右孩子結點,那么“左”和“右”應該對調。

case 2:

N的兄弟結點S是紅色的(從case 3開始S都是黑色的)。此時對調父結點P(肯定是黑色的)和兄弟結點S的顏色,然后將父結點P左旋。注意此時如果直接將N刪掉而結束,那么P結點的左邊只有一個黑色結點(NULL),而右邊有兩個黑色結點(S的左孩子和S的孫子結點(黑色的空葉子結點)),這樣就違反了屬性5,所以左旋之后將接着按case 4、case 5或case 6來處理。

        ________________#177#__________________________                    
        |                                             |                    
   _#103#______                       ________________~265~______          
   |          |                       |                         |          
#16#         _~146~_             _#206#______                  _#313#_     
             |     |             |          |                  |     |     
         #140#     #170#     #178#         _~236~_         #294#     #317# 
                                           |     |                         
                                       #208#     #253#                     

Deleting key 1th: 16 ---------------------------------------------------------------------

case 2 <16> (若當前結點的兄弟結點是紅色,則將父親和兄弟的顏色對調,若該結點靠左,則左旋父結點,若靠右則右旋父結點) : 
        ________________#177#__________________________                    
        |                                             |                    
   _~103~______                       ________________~265~______          
   |          |                       |                         |          
#16#         _#146#_             _#206#______                  _#313#_     
             |     |             |          |                  |     |     
         #140#     #170#     #178#         _~236~_         #294#     #317# 
                                           |     |                         
                                       #208#     #253#                     

左旋: 103
                  ______#177#__________________________                    
                  |                                   |                    
        ______#146#_                  ________________~265~______          
        |          |                  |                         |          
   _~103~_         #170#         _#206#______                  _#313#_     
   |     |                       |          |                  |     |     
#16#     #140#               #178#         _~236~_         #294#     #317# 
                                           |     |                         
                                       #208#     #253#                     

case 4 <16> (若當前結點的父結點為紅色,兄弟結點是黑色,且兄弟結點的左右子結點都為黑色,則將兄弟結點和父結點的顏色對調) : 
                  ______#177#__________________________                    
                  |                                   |                    
        ______#146#_                  ________________~265~______          
        |          |                  |                         |          
   _#103#_         #170#         _#206#______                  _#313#_     
   |     |                       |          |                  |     |     
#16#     ~140~               #178#         _~236~_         #294#     #317# 
                                           |     |                         
                                       #208#     #253#                     

case 0 <16> (將當前結點用子結點替代,之后釋放當前結點) : 
              ______#177#__________________________                    
              |                                   |                    
    ______#146#_                  ________________~265~______          
    |          |                  |                         |          
#103#_         #170#         _#206#______                  _#313#_     
     |                       |          |                  |     |     
     ~140~               #178#         _~236~_         #294#     #317# 
                                       |     |                         
                                   #208#     #253#                     

 



case 3:

結點N的父結點P,兄弟結點S以及S的孩子結點都是黑色的。此時簡單的將S設為紅色,這樣做可以讓通過S的所有路徑都少一個黑色節點,與通過N的路徑的黑色結點就相同了。但是,通過P的所有路徑現在比不通過P的路徑少了一個黑色節點,所以仍然違反性質5。要修正這個問題,我們要從case 1開始,在P上做重新平衡處理,並且一直遞歸到根結點為止,到根結點時,通過根結點的所有路徑都少了一個黑色結點,然后再從case 1返回。

         ______#236#______          
         |               |          
    _#178#_             _#294#_     
    |     |             |     |     
#177#     #206#     #253#     #317# 

Deleting key 5th: 253 ---------------------------------------------------------------------

case 3 <253> (若當前結點的父結點和兄弟結點是黑色,且兄弟結點的左右子結點都為黑色,則將兄弟結點變紅,將父結點轉到case 1做重新平衡處理) : 
         ______#236#______          
         |               |          
    _#178#_             _#294#_     
    |     |             |     |     
#177#     #206#     #253#     ~317~ 

case 3 <294> (若當前結點的父結點和兄弟結點是黑色,且兄弟結點的左右子結點都為黑色,則將兄弟結點變紅,將父結點轉到case 1做重新平衡處理) : 
         ______#236#______          
         |               |          
    _~178~_             _#294#_     
    |     |             |     |     
#177#     #206#     #253#     ~317~ 

case 1 <236> (若當前結點是根結點,直接返回) : 
case 0 <253> (將當前結點用子結點替代,之后釋放當前結點) : 
         ______#236#_          
         |          |          
    _~178~_         #294#_     
    |     |              |     
#177#     #206#          ~317~ 

 



case 4:

結點N的父結點P是紅色的,兄弟結點S以及S的兩個孩子結點(都是空葉子結點)都是黑色。此時將P和S的顏色對調,這不影響通過S的黑色結點數量,但是在通過N的路徑上增加了一個黑色結點,正好和要刪除的結點N相抵消,這樣屬性5被滿足了。

              ________________#236#______          
              |                         |          
    ______#177#______                  _#294#_     
    |               |                  |     |     
#146#_             _~206~_         #253#     #317# 
     |             |     |                         
     ~170~     #178#     #208#                     

Deleting key 6th: 208 ---------------------------------------------------------------------

case 4 <208> (若當前結點的父結點為紅色,兄弟結點是黑色,且兄弟結點的左右子結點都為黑色,則將兄弟結點和父結點的顏色對調) : 
              ________________#236#______          
              |                         |          
    ______#177#______                  _#294#_     
    |               |                  |     |     
#146#_             _#206#_         #253#     #317# 
     |             |     |                         
     ~170~     ~178~     #208#                     

case 0 <208> (將當前結點用子結點替代,之后釋放當前結點) : 
              ___________#236#______          
              |                    |          
    ______#177#______             _#294#_     
    |               |             |     |     
#146#_             _#206#     #253#     #317# 
     |             |                          
     ~170~     ~178~                          

 




case 5:

結點N的兄弟結點S的左孩子是紅色,右孩子是黑色(左紅右黑),並且結點N是父結點P的左孩子。此時將S與其左孩子的顏色對調,然后右旋S。注意此時通過父結點P的路徑都有相同的黑色結點數目,但是如果直接將N刪掉會違反屬性5(與case 2中類似),所以我們繼續按照case 6來處理。

         ___________#236#______          
         |                    |          
    _#177#______             _#294#_     
    |          |             |     |     
#170#         _#206#     #253#     #317# 
              |                          
          ~178~                          

Deleting key 1th: 170 ---------------------------------------------------------------------

case 5 <170> (subcase1: 若當前結點為左子結點,兄弟結點是黑色,且兄弟結點的左子結點為紅色,右子結點為黑色,則將兄弟結點和兄弟結點左孩子的顏色對調,再右旋兄弟結點) : 
         ___________#236#______          
         |                    |          
    _#177#______             _#294#_     
    |          |             |     |     
#170#         _~206~     #253#     #317# 
              |                          
          #178#                          

右旋: 206
         ___________#236#______          
         |                    |          
    _#177#_                  _#294#_     
    |     |                  |     |     
#170#     #178#_         #253#     #317# 
               |                         
               ~206~                     

case 6 <170> (將兄弟結點的顏色和父結點的顏色對調) : 
         ___________#236#______          
         |                    |          
    _#177#_                  _#294#_     
    |     |                  |     |     
#170#     #178#_         #253#     #317# 
               |                         
               ~206~                     

case 6 <170> (subcase1: 若當前結點為左子結點,則兄弟結點的右子結點必為紅色,將兄弟結點的右子結點變成黑色,將父結點左旋) : 
         ___________#236#______          
         |                    |          
    _#177#_                  _#294#_     
    |     |                  |     |     
#170#     #178#_         #253#     #317# 
               |                         
               #206#                     

左旋: 177
              ______#236#______          
              |               |          
         _#178#_             _#294#_     
         |     |             |     |     
    _#177#     #206#     #253#     #317# 
    |                                    
#170#                                    

case 0 <170> (將當前結點用子結點替代,之后釋放當前結點) : 
         ______#236#______          
         |               |          
    _#178#_             _#294#_     
    |     |             |     |     
#177#     #206#     #253#     #317# 

 

 

         ______#177#__________________________                    
         |                                   |                    
    _#146#_                  ________________~265~______          
    |     |                  |                         |          
#103#     #170#         _#206#______                  _#313#_     
                        |          |                  |     |     
                    #178#         _~236~_         #294#     #317# 
                                  |     |                         
                              #208#     #253#                     

Deleting key 12th: 313 ---------------------------------------------------------------------

若結點有兩個非空結點,用前驅代替它
         ______#177#__________________________                    
         |                                   |                    
    _#146#_                  ________________~265~______          
    |     |                  |                         |          
#103#     #170#         _#206#______                  _#294#_     
                        |          |                  |     |     
                    #178#         _~236~_         #294#     #317# 
                                  |     |                         
                              #208#     #253#                     

case 3 <294> (若當前結點的父結點和兄弟結點是黑色,且兄弟結點的左右子結點都為黑色,則將兄弟結點變紅,將父結點轉到case 1做重新平衡處理) : 
         ______#177#__________________________                    
         |                                   |                    
    _#146#_                  ________________~265~______          
    |     |                  |                         |          
#103#     #170#         _#206#______                  _#294#_     
                        |          |                  |     |     
                    #178#         _~236~_         #294#     ~317~ 
                                  |     |                         
                              #208#     #253#                     

case 5 <294> (subcase2: 若當前結點為右子結點,兄弟結點是黑色,且兄弟結點的左子結點為黑色,右子結點為紅色,則將兄弟結點和兄弟結點右孩子的顏色對調,再左旋兄弟結點) : 
         ______#177#__________________________                    
         |                                   |                    
    _#146#_                  ________________~265~______          
    |     |                  |                         |          
#103#     #170#         _~206~______                  _#294#_     
                        |          |                  |     |     
                    #178#         _#236#_         #294#     ~317~ 
                                  |     |                         
                              #208#     #253#                     

左旋: 206
         ______#177#__________________________                    
         |                                   |                    
    _#146#_                            ______~265~______          
    |     |                            |               |          
#103#     #170#              ______#236#_             _#294#_     
                             |          |             |     |     
                        _~206~_         #253#     #294#     ~317~ 
                        |     |                                   
                    #178#     #208#                               

case 6 <294> (將兄弟結點的顏色和父結點的顏色對調) : 
         ______#177#__________________________                    
         |                                   |                    
    _#146#_                            ______#265#______          
    |     |                            |               |          
#103#     #170#              ______~236~_             _#294#_     
                             |          |             |     |     
                        _~206~_         #253#     #294#     ~317~ 
                        |     |                                   
                    #178#     #208#                               

case 6 <294> (subcase2: 若當前結點為右子結點,則兄弟結點的左子結點必為紅色,將兄弟結點的左子結點變成黑色,將父結點右旋) : 
         ______#177#__________________________                    
         |                                   |                    
    _#146#_                            ______#265#______          
    |     |                            |               |          
#103#     #170#              ______~236~_             _#294#_     
                             |          |             |     |     
                        _#206#_         #253#     #294#     ~317~ 
                        |     |                                   
                    #178#     #208#                               

右旋: 265
         ______#177#________________                              
         |                         |                              
    _#146#_                  ______~236~______                    
    |     |                  |               |                    
#103#     #170#         _#206#_             _#265#______          
                        |     |             |          |          
                    #178#     #208#     #253#         _#294#_     
                                                      |     |     
                                                  #294#     ~317~ 

case 0 <294> (將當前結點用子結點替代,之后釋放當前結點) : 
         ______#177#________________                         
         |                         |                         
    _#146#_                  ______~236~______               
    |     |                  |               |               
#103#     #170#         _#206#_             _#265#_          
                        |     |             |     |          
                    #178#     #208#     #253#     #294#_     
                                                       |     
                                                       ~317~ 

 



case 6:

結點N的兄弟結點S是黑色的,S的右孩子是紅色的(右紅),並且結點N是父結點P的左孩子。此時將父結點P和兄弟結點S的顏色對調,再將S的右孩子變為黑色,然后左旋父結點P。
 

            ________________#177#__________________________                         
            |                                             |                         
   _____#103#______                       ________________~265~______               
   |              |                       |                         |               
#15#_            _~146~_             _#206#______                  _#294#_          
    |            |     |             |          |                  |     |          
    ~16~     #140#     #170#     #178#         _~236~_         #293#     #313#_     
                                               |     |                        |     
                                           #208#     #253#                    ~317~ 

Deleting key 14th: 293 ---------------------------------------------------------------------

case 6 <293> (將兄弟結點的顏色和父結點的顏色對調) : 
            ________________#177#__________________________                         
            |                                             |                         
   _____#103#______                       ________________~265~______               
   |              |                       |                         |               
#15#_            _~146~_             _#206#______                  _#294#_          
    |            |     |             |          |                  |     |          
    ~16~     #140#     #170#     #178#         _~236~_         #293#     #313#_     
                                               |     |                        |     
                                           #208#     #253#                    ~317~ 

case 6 <293> (subcase1: 若當前結點為左子結點,則兄弟結點的右子結點必為紅色,將兄弟結點的右子結點變成黑色,將父結點左旋) : 
            ________________#177#__________________________                         
            |                                             |                         
   _____#103#______                       ________________~265~______               
   |              |                       |                         |               
#15#_            _~146~_             _#206#______                  _#294#_          
    |            |     |             |          |                  |     |          
    ~16~     #140#     #170#     #178#         _~236~_         #293#     #313#_     
                                               |     |                        |     
                                           #208#     #253#                    #317# 

左旋: 294
            ________________#177#__________________________                         
            |                                             |                         
   _____#103#______                       ________________~265~___________          
   |              |                       |                              |          
#15#_            _~146~_             _#206#______                       _#313#_     
    |            |     |             |          |                       |     |     
    ~16~     #140#     #170#     #178#         _~236~_             _#294#     #317# 
                                               |     |             |                
                                           #208#     #253#     #293#                

case 0 <293> (將當前結點用子結點替代,之后釋放當前結點) : 
            ________________#177#__________________________                    
            |                                             |                    
   _____#103#______                       ________________~265~______          
   |              |                       |                         |          
#15#_            _~146~_             _#206#______                  _#313#_     
    |            |     |             |          |                  |     |     
    ~16~     #140#     #170#     #178#         _~236~_         #294#     #317# 
                                               |     |                         
                                           #208#     #253#                     

 

 

         ______#177#__________________________                    
         |                                   |                    
    _#146#_                  ________________~265~______          
    |     |                  |                         |          
#103#     #170#         _#206#______                  _#313#_     
                        |          |                  |     |     
                    #178#         _~236~_         #294#     #317# 
                                  |     |                         
                              #208#     #253#                     

Deleting key 12th: 313 ---------------------------------------------------------------------

若結點有兩個非空結點,用前驅代替它
         ______#177#__________________________                    
         |                                   |                    
    _#146#_                  ________________~265~______          
    |     |                  |                         |          
#103#     #170#         _#206#______                  _#294#_     
                        |          |                  |     |     
                    #178#         _~236~_         #294#     #317# 
                                  |     |                         
                              #208#     #253#                     

case 3 <294> (若當前結點的父結點和兄弟結點是黑色,且兄弟結點的左右子結點都為黑色,則將兄弟結點變紅,將父結點轉到case 1做重新平衡處理) : 
         ______#177#__________________________                    
         |                                   |                    
    _#146#_                  ________________~265~______          
    |     |                  |                         |          
#103#     #170#         _#206#______                  _#294#_     
                        |          |                  |     |     
                    #178#         _~236~_         #294#     ~317~ 
                                  |     |                         
                              #208#     #253#                     

case 5 <294> (subcase2: 若當前結點為右子結點,兄弟結點是黑色,且兄弟結點的左子結點為黑色,右子結點為紅色,則將兄弟結點和兄弟結點右孩子的顏色對調,再左旋兄弟結點) : 
         ______#177#__________________________                    
         |                                   |                    
    _#146#_                  ________________~265~______          
    |     |                  |                         |          
#103#     #170#         _~206~______                  _#294#_     
                        |          |                  |     |     
                    #178#         _#236#_         #294#     ~317~ 
                                  |     |                         
                              #208#     #253#                     

左旋: 206
         ______#177#__________________________                    
         |                                   |                    
    _#146#_                            ______~265~______          
    |     |                            |               |          
#103#     #170#              ______#236#_             _#294#_     
                             |          |             |     |     
                        _~206~_         #253#     #294#     ~317~ 
                        |     |                                   
                    #178#     #208#                               

case 6 <294> (將兄弟結點的顏色和父結點的顏色對調) : 
         ______#177#__________________________                    
         |                                   |                    
    _#146#_                            ______#265#______          
    |     |                            |               |          
#103#     #170#              ______~236~_             _#294#_     
                             |          |             |     |     
                        _~206~_         #253#     #294#     ~317~ 
                        |     |                                   
                    #178#     #208#                               

case 6 <294> (subcase2: 若當前結點為右子結點,則兄弟結點的左子結點必為紅色,將兄弟結點的左子結點變成黑色,將父結點右旋) : 
         ______#177#__________________________                    
         |                                   |                    
    _#146#_                            ______#265#______          
    |     |                            |               |          
#103#     #170#              ______~236~_             _#294#_     
                             |          |             |     |     
                        _#206#_         #253#     #294#     ~317~ 
                        |     |                                   
                    #178#     #208#                               

右旋: 265
         ______#177#________________                              
         |                         |                              
    _#146#_                  ______~236~______                    
    |     |                  |               |                    
#103#     #170#         _#206#_             _#265#______          
                        |     |             |          |          
                    #178#     #208#     #253#         _#294#_     
                                                      |     |     
                                                  #294#     ~317~ 

case 0 <294> (將當前結點用子結點替代,之后釋放當前結點) : 
         ______#177#________________                         
         |                         |                         
    _#146#_                  ______~236~______               
    |     |                  |               |               
#103#     #170#         _#206#_             _#265#_          
                        |     |             |     |          
                    #178#     #208#     #253#     #294#_     
                                                       |     
                                                       ~317~ 

 


免責聲明!

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



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