紅黑樹的刪除之3(共四篇)

  紅黑樹的刪除操作是紅黑樹最複雜的操作了,只要搞明白這個,基本上就明白紅黑樹的調整。刪除的情況大致可以分爲四種。

case 1. .刪除節點z,,子節點少於兩個時,左兒子爲T.NIL,用右兒子代替z

case 2. 刪除節點z,子節點少於兩個時,右兒子爲T.NIL,用左兒子代替z

case 3 刪除節點z,有兩個子節點時,找出後繼節點y,如果後繼節點y是右兒子,直接用y子樹替換z節點

case 4刪除節點z,有兩個子節點時,找出後繼節點y,如果後繼節點不是右兒子,用後繼節點的右兒子x子樹替換y子樹,再用後繼節點y子樹替換z節點。

下面看看圖形展示這四種刪除情況,其中z節點表示想要刪除的節點,y節點表示真正刪除的節點(從刪除節點的顏色角度來看),x表示要替換y的節點。由於y的顏色可能改變,用y-original-color表示y顏色改變之前的顏色

僞代碼如下:

RB-DELETE(T, z)
  y = z;
  y-original-color = y.color;
  if z.left == T.NIL
    x = z.right;
    RB-TRANSPLANT(T, z, z.right);
  else if z.right == T.NIL
    x = z.left;
    RB-TRANSPLANT(T, z, z.left);
  else y = TREE-MINMUM(z.right)
    y-original-color = y.color;
    x = y.right;
    if y.p = z;
      x.p = y;
    else RB-TRANSPLANT(T, y, y.right)
         y.right = z.right; 
         y.right.p = y;
    RB-TRANSPLANT(T, z, y)
    y.left = z.left;
    y.left.p = y;
    y.color = z.color;
  if y-original-color == black
    RB-DELETE-FIXUP(T, x)

 

  可以看到,如果y是黑色的,就肯定破壞了紅黑樹的性質了。如果y是紅色的,紅黑樹性質依然保持,因爲樹的黑高沒有改變,也不存在兩個相鄰的的紅色節點,性質4和5沒有任何改變。所以y是黑色的時候需要通過RB-DELETE-FIXUP來調整修正。下面來看看如何調整。

 違反性質2的情況:如果y是原來的根節點,而y的一個紅色孩子成爲新的根幾點,就違反了性質2,但是這很容易解決,直接染黑就是了,不再繼續討論這種情況。

 違反性質4的情況:x節點爲紅色,x的父節點也爲紅色,這種情況也很容易解決,染黑x就是了。

 剩下的情況就是隻違反了性質5,只要調整好性質5就好了,這裏有一個技巧,就是把x節點視爲還有一層黑色,問題就變成了解決違反性質1了,也就是把x看成既紅又黑,我們只要把這層額外的黑色不斷往上推,直到推給了一個紅色節點,那麼子樹的黑高就恢復了。和插入一樣,有個關鍵思想是,轉換過程中千萬不能破壞其他任何的性質。經過分析,破壞性質1(本質上是破壞性質5)有以下五種情況:

  case 1 x是紅色的

  case 2. x的兄弟節點w是紅色的

  case 3 x的兄弟節點w是黑色的,而且w的兩個子節點都是黑色的

  case 4 x的兄弟節點w是黑色的,w的左兒子是紅色的,w的右孩子是黑色的

 case 5  x的兄弟節點w是黑色的,且w的右孩子是紅色的。

如下圖所示:

case 1是最容易解決的,直接染黑就是了。

case 2的話,改變w和x.p的顏色,左旋轉x.p,這樣子不改變任何性質的同時,把case 2轉變爲case 3,4,5。不做詳細討論

僞代碼爲:

 

w.color = black;
x.p.color = red;
LEFT-ROTATE(T, x.p)
w = x.p.right;

 

 

 

case 3的話,可以認爲從x和w去掉一層黑色給x.p,如果x.p爲原本爲紅色的話,那麼x的子樹黑高加一,w子樹黑高不變,性質就恢復好了,如果x.p原來爲黑色的,那麼認爲x.p的整個子樹黑高都少了1,多了的一層黑色就給了x.p,case3就轉爲case 2,3,4,5了。

僞代碼如下:

 

  w.color = red;
  x = x.p


case 4的情況左侄兒爲紅,右侄兒爲黑,這種情況統一轉case 5來處理。

 

這裏右旋w並且沒有改變紅黑樹的五大性質,轉爲了case5。僞代碼如下:

 

w.left.color = black;
w.color = red;
RIGHT-ROTATE(T, w)
w = x.p.right;


case 5的情況是紅黑樹調整的出口,只要到達了case 5,調整完就能恢復所有性質了。調整如下圖所示:

 

接下來分析case5的轉換過程,這裏的思路是這樣的:首先我們要讓x子樹黑高加一,那麼就左旋轉a,左旋轉後d的左子樹沒有任何問題,但是右子樹黑高可能減少了1(如果a原來是黑色的情況),爲了解決這個問題,可以把a和d顏色交換,然後染黑c,這樣左旋轉後的d的右子樹的黑高也就不會有任何改變了。僞代碼如下:

 

w.color = x.p.color;
x.p.color = black;
w.right.color = black;
LEFT-ROTATE(T, x.p);
x = T.root;

 

 

 

爲了能在全局下看到調整情況,下面展示整個刪除調整的過程僞代碼:

 

RB-DELETE-FIXUP(T, x)
 while x != T.root && x.color = black
   if x == x.p.left
     w = x.p.right
     // case 2
     if w.color = red
       w.color = black;
       x.p.color = red;
       LEFT-ROTATE(T, x.p)
       w = x.p.right;
     // case 3
     if w.left.color == black && w.right.color == black
       w.color = red;
       x = x.p;
     // case 4
     else if w.right.color == black
       w.left.color = black;
       w.color = red;
       RIGHT-ROTATE(T, w)
       w = x.p.right;
     // case 5
     w.color = x.p.color;
     x.p.color = black;
     w.right.color = black;
     LEFT-ROTATE(T, x.p);
     x = T.root;

 

 

 

 

 

 

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