2013-01-19 141 views
4

我在平衡AVL樹方面遇到了問題。我已經搜索了高低的步驟,以便如何平衡它們,並且我無法得到任何有用的東西。平衡AVL樹

我知道有4種:

  • 單左旋轉
  • 單權流轉
  • 雙左 - 右旋轉
  • 雙右向左旋轉

但我只是不能得到如何選擇其中之一將哪個節點應用於

任何幫助將不勝感激!

回答

2

這是Java實現,你會得到的算法存在的想法:

private Node<T> rotate(Node<T> n) { 
    if(n.getBf() < -1){ 
      if(n.getRight().getBf() <= 0){ 
       return left(n);   
      } 
      if(n.getRight().getBf() > 0){ 
       return rightLeft(n); 
      } 
    } 
    if(n.getBf() > 1){ 
      if(n.getLeft().getBf() >= 0){ 
       return right(n); 
      } 
      if(n.getLeft().getBf() < 0){ 
       return leftRight(n); 
      } 
    } 
    return n; 
} 

4個旋轉的單獨的方法在這裏:

/** 
* Performs a left rotation on a node 
* 
* @param n The node to have the left rotation performed on 
* @return The new root of the subtree that is now balanced due to the rotation 
*/ 
private Node<T> left(Node<T> n) { 
    if(n != null){ 
     Node<T> temp = n.getRight(); 
     n.setRight(temp.getLeft()); 
     temp.setLeft(n); 
     return temp; 
    } 
    return n; 
} 

/** 
* Performs a right rotation on a node 
* 
* @param n The node to have the right rotation performed on 
* @return The new root of the subtree that is now balanced due to the rotation 
*/ 
private Node<T> right(Node<T> n) { 
    if(n != null){ 
     Node<T> temp = n.getLeft(); 
     n.setLeft(temp.getRight()); 
     temp.setRight(n); 
     return temp; 
    } 
    return n; 
} 

/** 
* Performs a left right rotation on a node 
* 
* @param n The node to have the left right rotation performed on 
* @return The new root of the subtree that is now balanced due to the rotation 
*/ 
private Node<T> leftRight(Node<T> n) { 
    n.setLeft(left(n.getLeft())); 
    Node<T> temp = right(n); 
    return temp; 
} 

/** 
* Performs a right left rotation on a node 
* 
* @param n The node to have the right left rotation performed on 
* @return The new root of the subtree that is now balanced due to the rotation 
*/ 
private Node<T> rightLeft(Node<T> n) { 
    n.setRight(right(n.getRight())); 
    Node<T> temp = left(n); 
    return temp; 
} 
0

AVL樹中的關鍵不變量是每個節點的平衡因子是-1,0或+1。這裏,「平衡因子」是左側和右側子樹之間高度的差異。 +1表示左側子樹比右側子樹高一個,-1表示左側子樹比右側子樹短一些,0表示子樹的大小相同。這些信息通常緩存在每個節點中。

當您獲得平衡因子爲-2或+2的節點時,您需要進行旋轉。下面是當旋轉是必要的一個可能的設置:

  u (-2) 
     /\ 
     A v (-1) 
     /\ 
      B C 

如果我們填寫這些樹的高度,我們得到

  u h + 2 
     /\ 
    h-1 A v h + 1 
     /\ 
     h-1 B C h 

如果發生這種情況,做一個單一的右旋轉產量

  v h+1 
     /\ 
    h u C h 
    /\ 
h-1 A B h-1 

嘿!樹是平衡的。這棵樹的鏡像也可以用一個左旋轉來解決。

所有AVL樹的旋轉都可以簡單地通過枚舉小範圍內的可能的平衡因子,然後確定在每一步應該應用哪些旋轉來確定。我會把這個作爲練習留給讀者。 :-)如果你只是想查找答案,Wikipedia article on AVL trees有一個很好的圖片,總結了可能需要應用的所有旋轉。

希望這會有所幫助!

+1

是不是這棵樹已經平衡? u + A = 2,u + v + c = 3, 2-3 = -1,則它是平衡的。 我們爲什麼要在這裏做一個輪換? – user1910524

+1

@ user1910524-不,這棵樹不平衡。請注意,其左側和右側子樹的高度差異爲2 - 左側子樹的高度爲h - 1,右側子樹的高度爲h + 1。請記住,平衡係數代表兩棵樹之間的高度差異,所以說「u + A = 2」不是一個有意義的計算。那有意義嗎? – templatetypedef

+1

@ templatetypedef,我不明白。如果我們看一下左邊的「u」,我們可以找到水平= 2.如果我們看一下「u」的rightsubtree,我們可以找到水平= 3。所以2-3 = -1。 如果我們看「v」的左半部分,我們可以找到水平= 2。如果我們查看「v」的rightsubtree,我們可以找到水平= s。所以2-2 = 0。 所以樹是平衡的! – user1910524