爲何 AVL 樹只須要 LL,LR,RR,RL 四種旋轉?

問題:爲何 AVL 樹只須要 LL,LR,RR,RL 四種旋轉?code

首先說明一下本文所使用的記號:總結

  • T(N):以節點 N 爲根的樹co

  • L(T)、R(T):樹T的左右子樹數字

  • H(T):樹T的高度

  • DH(T):左右子樹高度之差,即 H(R(T)) - H(L(T))

  • |DH(T)|:左右子樹高度之差的絕對值

須要旋轉的兩種狀況

給定一棵樹 T(1)(固然,它可能也是其它樹的子樹,不過這不影響討論),根據 AVL 對「平衡」的定義(|DH(T)| < 2),只有當樹 T(1) 處於以下兩種狀況時,才須要旋轉(注意:|DH(T(1))| 不可能 > 2):

1. DH(T(1)) == -2

          1
       /     \
    2(n+2)   3(n)
            
2. DH(T(1)) == 2

          1
       /     \
     2(n)   3(n+2)

再說明一下標記,上面 一、二、3 這些數字,表示樹的節點;3(n+2) 表示以節點 3 爲根的子樹高度爲n+2。

如今,以 DH(T(1)) == -2 爲例,就【插入】和【刪除】兩種操做分別加以討論。而 DH(T(1)) == 2 的狀況與此相似,再也不贅述。

插入

插入以前的 T(1)

若是 DH(T(1)) == -2 是由【插入】引發的,則插入以前的 T(1) 應爲:

DH(T(1)) == -1

        1                  
     /     \    
  2(n+1)   3(n)                
                                          
展開爲:
          1
       /     \
    2(n+1)   3(n)
   /     \
 4(?)    5(?)

T(4),T(5) 的高度可取值以下:

H(T(4))  H(T(5))
a.   n         n
b.   n         n-1
c.   n-1       n

但 b, c 其實都不可能。好比 b,要使 DH(T(1)) == -2,只能插入節點到 T(4),而一旦這樣插入了,又會使 DH(T(2)) == -2 了。因此插入以前的 T(1) 應爲:

1
       /     \
    2(n+1)    3(n)
   /     \
 4(n)   5(n)

插入節點到 T(4) 的狀況

以下圖。旋轉也一併給出,記這種旋轉爲 rotate1(其實就是 LL)。

1
        /     \
       2     3(n)
    /     \
 4(n+1)   5(n)

rotate1:
           2
        /     \
       /       1
      /      /   \
  4(n+1)   5(n)  3(n)

插入節點到 T(5) 的狀況

1
         /     \
        2     3(n)
     /     \
    4(n)  5(n+1)

如何旋轉以達到平衡,並不明顯。必須將節點 5 進一步展開來看:

1
         /     \
        2     3(n)
     /     \
    4(n)   5(n+1)
         /     \
       6(?)   7(?)

T(6),T(7) 的高度可取值以下:

H(T(6))  H(T(7))
a.   n        n
b.   n        n-1
c.   n-1      n

但 a 不可能。不然,在新節點插入以前,H(T(5))就已經爲 n+1,而 T(1) 就已經不平衡了。

b, c 都有可能。若是是 b,新節點插入到 T(6);若是是 c,新節點插入到 T(7)。因此插入節點到T(5) 的情形最終應該是:

1
      /     \
     2     3(n)
  /     \
4(n)     5(n+1)
      /         \
  6(n/n-1)   7(n-1/n)

rotate2:
         5
      /     \
     2       1
   /   \   /   \
 4(n)  6   7   3(n)

rotate2 其實就是 LR。

關於【插入】的小結

總結一下,對於【插入】,有以下 2種旋轉:

1
       /     \
      2     3(n)
   /     \
4(n+1)   5(n)

rotate1:
           2
        /     \
       /       1
      /      /   \
  4(n+1)   5(n)  3(n)
1
        /     \
       2     3(n)
    /     \
   4(n)    5
        /    \
    6(n/n-1) 7(n-1/n)
     
rotate2:
           5
        /     \
       2       1
     /   \   /   \
   4(n)  6   7  3(n)

刪除

刪除以前的 T(1)

若是 DH(T(1)) == -2 是由【刪除】引發的,則刪除以前的 T(1) 應爲:

DH(T(1)) == -1

        1
     /     \
  2(n+2)  3(n+1)

展開爲:
          1
       /     \
      2     3(n+1)
   /     \
 4(?)    5(?)

T(4),T(5) 的高度可取值以下:

H(T(4))    H(T(5))
a.   n+1    n+1 - DH(T(2)) : 0
b.   n+1    n   - DH(T(2)) : -1
c.   n      n+1 - DH(T(2)) : 1

這三種都有可能,因此刪除以前的 T(1) 爲:

A.                                 
           1                       
        /     \                   
       2     3(n+1)                
    /     \                      
 4(n+1)  5(n+1/n)              

B.
           1
        /     \
      2     3(n+1)
           /     \
        4(n)    5(n+1)

對於 T(1) A 的旋轉

對於 T(1) A,從子樹 T(3) 刪除節點而使 H(T(3)) 減 1 後,獲得須要旋轉的樹以下:

1
        /     \
       2     3(n)
    /     \
 4(n+1)  5(n+1/n)

rotate1:
          2
       /     \
      /       1
     /     /     \
 4(n+1) 5(n+1/n) 3(n)

旋轉也一併給出。一樣仍是 rotate1。

對於 T(1) B 的旋轉

對於 T(1) B,從子樹 T(3) 刪除節點而使 H(T(3)) 減 1 後,獲得須要旋轉的樹以下:

1
        /     \
       2     3(n)
    /     \
 4(n)    5(n+1)

如何旋轉以達到平衡,並不明顯。須將節點 5 進一步展開來看:

1
        /     \
       2     3(n)
   /     \
 4(n)     5
       /     \
      6(?)  7(?)

T(6),T(7) 的高度可取值以下:

H(T(6))    H(T(7))
    n          n
    n          n-1
    n-1        n

這三種都有可能。因此 T(1) B 的情形最終爲:

1
         /     \
        2     3(n)
     /     \
   4(n)     5
         /     \
  6(n/n/n-1)  7(n/n-1/n)

rotate2:

           5
        /     \
      2         1
    /   \    /   \
 4(n)    6  7    3(n)

旋轉仍是 rotate2。

關於【刪除】的小結

總結一下,對於【刪除】,有以下 2 種旋轉:

1
        /     \
       2     3(n)
    /     \
 4(n+1)  5(n+1/n)

rotate1:
          2
       /     \
      /       1
     /     /     \
 4(n+1) 5(n+1/n) 3(n)
1
         /     \
        2     3(n)
     /     \
   4(n)     5
         /     \
  6(n/n/n-1)  7(n/n-1/n)

rotate2:
           5
        /     \
      2         1
    /   \    /   \
 4(n)    6  7    3(n)

結論

對於 DH(T(1)) == -2,共有 2 種旋轉,如上 rotate1 和 rotate2。雖然對於【插入】和【刪除】,旋轉時平衡點的調整更新可能會有所不一樣,但其旋轉的方式是一致的。

最後,rotate1 即所謂的 LL,rotate2 即所謂的 LR。若是再去分析 DH(T(1)) == 2 的話,同理能夠獲得 RR 和 RL。

相關文章
相關標籤/搜索