1. 程式人生 > >平衡二叉樹之二(刪除節點)

平衡二叉樹之二(刪除節點)

類似於新增操作,從平衡二叉樹中刪除節點也分為兩步,第一步完成節點的刪除,第二步找到因為刪除而導致不滿足平衡二叉樹要求的子樹並對其進行調整。

一、 刪除節點

從平衡二叉樹中刪除節點更為複雜。首先第一步需要找到要刪除的節點x,並分情況進行處理:

  1. 如果要刪除的節點為葉子節點,就找到了要刪除的節點
  2. 如果要刪除的節點為只有一棵子樹的節點就找到了要刪除的節點
  3. 如果要刪除的節點既有左子樹,又有右子樹,則
  • 如果該節點的平衡因子為0或者1,則找到其左子樹中具有最大值的節點max(我們只討論有序平衡二叉樹,並且有序平衡二叉樹中任意一個節點的左子樹上的所有節點的值小於該節點的值,右子樹上所有節點的值大於該節點的值),將max的內容與x的內容交換(只替換儲存的真正的資料,不替換指標,平衡因子等用於管理目的的資訊),並且max即為新的要刪除的節點。由於樹是有序的,因而這樣找到的節點要麼是一個葉子節點,要麼是一個沒有右子樹的節點。
  • 如果該節點的平衡因子為-1,則找到其右節點中具有最小值的節點min,將min的內容與x的內容交換,並且min即為新的要刪除的節點。由於樹是有序的,因而這樣找到的節點要麼是一個葉子節點,要麼是一個沒有左子樹的節點。

在找到要刪除的節點後下一步就是刪除節點,假設要刪除的節點為delete,其父節點為parent,顯然此時delete要麼是一個葉子節點,要麼是一個只有一棵子樹的節點:

  • 如果delete是一個葉子節點,則直接刪除它
  • 如果delete是一個只有一棵子樹的節點,則將delete刪除,delete節點的子樹的根將成為parent的子節點

無論是這兩種情形中的哪一種都會導致節點parent的以delete節點為根節點的子樹的高度降低,因此下一步就是處理高度降低的影響。假設刪除節點導致以節點A為根的子樹的高度降低了,並且A的父節點為B則:

  • 如果B為NULL,即A已經為根節點,則刪除完成
  • 否則考察B的平衡因子:
    • 平衡因子為0,只需要調整平衡因子即可完成刪除
    • 平衡因子表示以A為子樹的根的高度較高,則B的新的平衡因子為0,以B為根的子樹的高度降低,需要回溯往前繼續處理高度降低的影響
    • 平衡因子表示以A為子樹的根的高度較矮,則以B為根的子樹違背了平衡二叉樹的要求,需要對以B為根的子樹進行調整,如果調整完後得到的新的子樹的高度和原來以B為根的子樹的高度相同,則刪除完成,否則新得到的子樹的高度與原來的以B為根的子樹的高度相比必然是減小了,因而還需要繼續往前回溯處理高度降低的影響
比如要下從下圖中刪除節點20


首先找到替換20被刪除的節點15,並將二者內容替換,如下圖所示:


然後刪除節點20得到下圖:


在刪除節點20後,節點10違反了平衡二叉樹的性質,對以10為根節點的子樹進行調整(類似於插入時,需要先做一次左旋再做一次右旋)可得下圖:


二、刪除中的調整

刪除節點時的調整基本上類似於插入時的調整,但是也有些區別,以從節點A的左子樹刪除節點導致其左子樹高度降低而需要調整為例進行分析。並分以下情況:

2.1 A的右子樹的平衡因子為-1

該情形如下圖所示:


該情形很簡單,只需要做一次左旋即可。

首先分析調整對以A為根的子樹的高度的影響,顯然調整後子樹的高度降低了。

再分析調整對參與調整的節點的平衡因子的變化,此時只需要考慮孩子域被修改的節點,因為只有這種節點的平衡因子才會變化。在這種調整中只有A以及其右子樹的根節點的孩子域會發生變化,因而只需要分析它們兩個的平衡因子的變化(以上圖為例來分析,要分析的兩個節點為20,30):

  • 假設以節點20為根的子樹的高度為h1,則刪除節點前:
    • 由於節點20的平衡因子為-1(否則從左子樹刪除節點導致其左子樹高度降低就不需要進行調整),因此其右子樹(以30為根節點的子樹)的高度為h1-1,其左子樹(以10為根節點的子樹)的高度為h1-2
    • 對於節點20的右孩子節點30來說,由於它的平衡因子為-1,因此它的左子樹(以25為根節點的子樹)的高度為(h1-1)- 2,它的右子樹(以40為根節點的子樹)的高度為(h1-1)- 1
  • 刪除節點後:
    • 節點20的左子樹(以10為根節點的子樹)的高度變為h1-2 -1
  • 調整後
    • 節點10和節點25分別成為節點20的左右子樹,分別以二者為根的子樹的高度差為h1 - 2 - 1 - ((h1-1)- 2) = 0
    • 以節點20為根節點的子樹的高度為h1-2 -1 + 1
    • 節點20和節點40分別成為節點30的左右子樹,分別以二者為根的子樹的高度差為(h1-2 -1 + 1) -  ( (h1-1)- 1 ) = 0
因而該種情形的最終結果是子樹高度降低,參與調整的節點A以及其右子樹的根節點在調整後的平衡因子都為0,其它節點平衡因子不變。

2.2 A的右子樹的平衡因子為0

該情形如下圖所示:


類似於上一種情形,該情形只需要做一次左旋即可。

首先分析調整對以A為根的子樹的高度的影響,顯然調整後子樹的高度不變。

再分析調整對參與調整的節點的平衡因子的變化,此時只需要考慮孩子域被修改的節點,因為只有這種節點的平衡因子才會變化。在這種調整中只有A以及其右子樹的根節點的孩子域會發生變化,因而只需要分析它們兩個的平衡因子的變化(以上圖為例來分析,要分析的兩個節點為20,30):

  • 假設以節點20為根的子樹的高度為h1,則刪除節點前:
    • 由於節點20的平衡因子為-1(否則從左子樹刪除節點導致其左子樹高度降低就不需要進行調整),因此其右子樹(以30為根節點的子樹)的高度為h1-1,其左子樹(以10為根節點的子樹)的高度為h1-2
    • 對於節點20的右孩子節點30來說,由於它的平衡因子為0,因此它的左右子樹(以25為根節點的子樹和以40為根節點的子樹)的高度都為(h1-1)- 1
  • 刪除節點後:
    • 節點20的左子樹(以10為根節點的子樹)的高度變為h1-2 -1
  • 調整後
    • 節點10和節點25分別成為節點20的左右子樹,分別以二者為根的子樹的高度差為h1 - 2 - 1 - ((h1-1)- 1) = -1
    • 以節點20為根節點的子樹的高度為h1-1 -1 + 1
    • 節點20和節點40分別成為節點30的左右子樹,分別以二者為根的子樹的高度差為(h1- 1 -1 + 1) -  ( (h1-1)- 1 ) = 1
因而該種情形的最終結果是子樹高度不變,參與調整的節點A以及其右子樹的根節點在調整後的平衡因子分別為-1,1,其它節點平衡因子不變。

2.3 A的右子樹的平衡因子為1

該情形如下圖所示:


和前兩種情形不同,該種情形下需要做兩次調整,一次右旋、一次左旋。

首先分析調整對以A為根的子樹的高度的影響,調整後子樹的高度降低。

再分析調整對參與調整的節點的平衡因子的變化,此時只需要考慮孩子域被修改的節點,因為只有這種節點的平衡因子才會變化。在這種調整中只有A,A的右孩子,A的右孩子的左孩子的孩子域會發生變化,因而只需要分析它們的平衡因子的變化(以上圖為例來分析,要分析的三個節點為20,30,25):

  • 假設以節點20為根的子樹的高度為h1,則刪除節點前:
    • 由於節點20的平衡因子為-1(否則從左子樹刪除節點導致其左子樹高度降低就不需要進行調整),因此其右子樹(以30為根節點的子樹)的高度為h1-1,其左子樹(以10為根節點的子樹)的高度為h1-2
    • 對於節點20的右孩子節點30來說,由於它的平衡因子為1,因此它的左子樹(以25為根節點的子樹)的高度為h1-1-1,它的右子樹(以40為根節點的子樹)的高度為(h1-1)- 2
  • 刪除節點後:
    • 節點20的左子樹(以10為根節點的子樹)的高度變為h1-2 -1
  • 調整後,節點10和節點25的左孩子分別成為節點20的左右子樹,節點25的右孩子和節點40分別成為節點30的左右孩子,節點20和節點30分別成為節點25(即新的根)的左右子樹。則:
    • 如果節點10不存在,即刪除節點後20的左子樹消失,則此種情形下,刪除完節點後,節點23,25,40都不能存在,調整完後三者平衡因子都為0
    • 如果節點10存在,則節點25的左右子樹至少有一個不能為空,此時:
      • 如果刪除前節點25的平衡因子為1,則此時
        • 節點20的平衡因子為: “以節點10為根的子樹的高度 - 以節點25的左孩子為根的子樹的高度”= h1-2 -1 - ((h1 -1 -1) -1)= 0
        • 節點30的平衡因子為: “以節點25的右孩子為根的子樹的高度 - 以節點40為根的子樹的高度”= ((h1-1-1)- 2)- ((h1 -1) - 2)= -1
        • 節點25的平衡因子為:“以節點20為根的子樹的高度 - 以節點30為根的子樹的高度”= ((h1-2 -1) + 1)- (((h1 -1) - 2 )+ 1) = 0
      • 如果刪除前節點25的平衡因子為0,則此時:
        • 節點20的平衡因子為: “以節點10為根的子樹的高度 - 以節點25的左孩子為根的子樹的高度”= h1-2 -1 - ((h1 -1 -1) -1)= 0
        • 節點30的平衡因子為: “以節點25的右孩子為根的子樹的高度 - 以節點40為根的子樹的高度”= ((h1-1-1)- 1)- ((h1 -1) - 2)= 0
        • 節點25的平衡因子為:“以節點20為根的子樹的高度 - 以節點30為根的子樹的高度”= ((h1-2 -1) + 1)- (((h1 -1) - 2 )+ 1) = 0
      • 如果刪除前節點25的平衡因子為-1,則此時:
        • 節點20的平衡因子為: “以節點10為根的子樹的高度 - 以節點25的左孩子為根的子樹的高度”= h1-2 -1 - ((h1 -1 -1) -2)= 1
        • 節點30的平衡因子為: “以節點25的右孩子為根的子樹的高度 - 以節點40為根的子樹的高度”= ((h1-1-1)- 1)- ((h1 -1) - 2)= 0 
        • 節點25的平衡因子為:“以節點20為根的子樹的高度 - 以節點30為根的子樹的高度”= ((h1-2 -1) + 1)- (((h1 -1) - 2 )+ 1) = 0
因而該種情形的最終結果是子樹高度降低,假設被調整的子樹的根節點為A,其右孩子為B,B的左孩子為C,則調整後A,B,C的平衡因子分別為:
  • C的平衡因子為0
  • 如果刪除前C的平衡因子為0,則A和B的平衡因子為0
  • 如果刪除前C的平衡因子為1,則A的平衡因子為0,B的平衡因子為-1
  • 如果刪除前C的平衡因子為-1,則A的平衡因子為1,B的平衡因子為0

從右子樹刪除和從左子樹是對稱的。

從上述分析可以看出從平衡二叉樹中刪除節點的時間複雜度和新增相同也是O(logn)