4

I am having trouble balancing AVL Trees. I have searched high and low for steps to how to balance them and I just can't get anything useful.

I know there are 4 kinds:

  • Single Left Rotation
  • Single Right Rotation
  • Double Left-Right Rotation
  • Double Right-Left Rotation

But I just can't get how to choose which one of them and which node to apply it on!

Any help would be greatly appreciated!

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
user1910524
  • 113
  • 3
  • 12

2 Answers2

2

This is the java implementation and you will get the idea of the algorithm there:

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;
}

The separate methods for 4 rotations are here:

/**
 * 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;
}
gtboy
  • 128
  • 1
  • 3
  • 12
0

The key invariant in an AVL tree is that the balance factor of each node is either -1, 0, or +1. Here, the "balance factor" is the difference in the height between the left and right subtrees. +1 means the left subtree is one taller than the right subtree, -1 means the left subtree is one shorter than the right subtree, and 0 means the subtrees have the same size. This information is usually cached in each node.

When you get a node with a balance factor of -2 or +2, you will need to do a rotation. Here's one possible setup for when a rotation is necessary:

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

If we fill in the heights of these trees, we get

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

If this happens, doing a single right rotation yields

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

And hey! The tree is balanced. The mirror-image of this tree would also be fixable with a single left rotation.

All of the AVL tree rotations can be determined simply by enumerating the possible balance factors within a small range and then determining which rotations should be applied at each step. I'll leave this as an exercise to the reader. :-) If you just want to look up the answers, the Wikipedia article on AVL trees has a nice picture that summarizes all the rotations that might need to be applied.

Hope this helps!

Community
  • 1
  • 1
templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • 1
    isn't this tree already balanced? u+A =2 , u+v+c=3 , 2-3 = -1, then it is balanced. Why would we do a rotation here? – user1910524 Jan 19 '13 at 22:20
  • 1
    @user1910524- No, this tree is not balanced. Notice that its left and right subtrees differ in height by 2 - the left subtree has height h - 1 and the right subtree has height h + 1. Remember that the balance factor represents the height difference across the two trees, so saying "u + A = 2" is not a meaningful calculation. Does that make sense? – templatetypedef Jan 19 '13 at 22:54
  • 1
    @ templatetypedef, I don't understand. If we look at the leftsubtree of "u", we find the levels = 2. If we look at the rightsubtree of "u", we find the levels = 3. So 2-3=-1. And if we look at the leftsubtree of "v", we find the levels = 2. If we look at the rightsubtree of "v", we find the levels = s. So 2-2=0. So the tree is balanced! – user1910524 Jan 19 '13 at 23:10
  • 1
    @user1910524- Oh, I see. A, B, and C denote arbitrary subtrees of a certain height, rather than individual nodes. u and v refer to individual nodes rather than subtrees. I should have been more clear with my notation. Does that make sense? – templatetypedef Jan 19 '13 at 23:11