Data Structures

Professor Abdul-Quader

Lesson 7 (Tree Rotations / AVL Trees)

Presentations

Four presentations today.

Project 1

Project 1 is due Sunday. Questions?

Tree Rotations

Binary Tree with root E, children C and F; C has children B and D; B has child A. This is rotated right to a tree with root C, children B and E, B has child A, E has children D and F

  • Preserves “Search Tree” property
  • Algorithm?

Right Rotation

L = root.left
root.left = L.right
L.right = root
return L

Makes L the new root of this subtree.

Left Rotation

Similar idea:

R = root.right
root.right = R.left
R.left = root
return R
  • Makes R the new root of this subtree
  • Inverse operations:
    • Right rotation followed by left rotation?

Exercise

Draw the trees we obtain after the following sequence of operations:

  • (Create a new tree)
  • Insert 0, 4, 2
  • Rotate right around 4
  • Insert -1, 1
  • Rotate left around 0

Balancing

What does an “unbalanced” tree look like?

Unbalanced Trees

Right-right unbalanced tree
Right-left unbalanced tree

Unbalanced Trees

  • Can also define left-right and left-left unbalanced trees
  • In general:
    • if heights of left and right subtrees differ by more than 1
  • Keep track of the height of each node
  • If one subtree has a larger height than the other, rebalance
  • How do we rebalance? Tree rotations!

Algorithms for balancing

Some unbalanced trees can be rebalanced easily:

  • right-right: rotate left
  • left-left: rotate right

Right-left

Right-left unbalanced tree

  • Rotate left around 30?
  • Rotate right around 30? (can’t!)
  • Solution?

Exercise

Forget about the code for a bit. What should a self-balancing tree do when we insert in the following order: 1, 2, 3, 4, 5, 6, 7?

Draw the pictures of the BSTs that result. When do we trigger a “rebalancing”?

Visualization

Self-balancing

Again:

  • Each node keeps track of a “height”
  • Ideally: heights of the left/right subtrees are equal
  • If there are exactly 8 nodes? What’s the most “balanced” tree?

Self-balancing pseudocode

// pseudocode
private TreeNode<T> insert(T item, TreeNode<T> subtree) {
   // code to insert
   int balance = height(subtree.left) - height(subtree.right);
   if (balance > 1) {
     // left-left or left-right?
     // check height()
   } else if (balance < -1) {
     // right-right or right-left?
   }
}

RR

BST with 10->15->20, rotate left around 10

Right-right: rotate left

RL

BST with 10->20->15, rotate right around 20, then left around 10

Right-left: rotate right around 20, then left around 10.

Difference?

Right-right unbalanced tree

  • How to tell right-right vs right-left?
  • height(subtree.right.right) >= height(subtree.right.left)

Code Snippet

private TreeNode<T> balance(TreeNode<T> subtree) {
   int balance = height(subtree.left) - height(subtree.right);
   if (balance > 1) {
     // left-left
     if (height(subtree.left.left) >= height(subtree.left.right)) {
       subtree = rotateRight(subtree);
     } else {
       // left-right
       // left rotation turns this into left-left
       subtree.left = rotateLeft(subtree.left);
       // right rotation rebalances
       subtree = rotateRight(subtree);
     }

   } else if (balance < -1) {
     // right-right or right-left?
     // do the opposite as above
   }

   // update height
   subtree.height = 1 + Math.max(height(subtree.left), height(subtree.right));
   return subtree;
}

Video

Analysis

  • Adelson-Velsky, Landis (1962): AVL Trees
  • Height is \(O(\log(n))\)
  • So contains is \(O(\log(n))\).
  • Insert/remove may trigger rebalancings. How many?
    • Only up one branch of the tree! So still \(O(\log(n))\).
  • Adelson-Velsky/Landis proved: worst case height is about \(1.44 \log(n)\).

Video

In the above video, I go through the proof that all the operations are \(O(\log(n))\).

Challenge questions

  • Tree (not necessarily BST / AVL): Level-order traversal
  • AVL Tree Sort / running times
  • Tree (not necessarily BST / AVL): Path from root to a node N
  • Tree (not necessarily BST / AVL): Node N, height \(h\), find ancestor of \(N\) that is \(h\) levels above.
  • Tree (not necessarily BST / AVL): two nodes, find lowest common ancestor

Level-order

Given a tree T, output its nodes in level-order. That is, output the root first, then output the root’s children, then the grandchildren, etc.

Hint:

  • Nothing to do with BST
  • We’ve seen this before (kind of)…?

AVL Sort

Implement a method in the AVL Tree class which returns a List of items in sorted order:

public List<T> sort() {
  // your code here
  
}

Asymptotic running time (if the tree has \(N\) elements)?

AVL Sort (continued)

Asymptotic running time of the following:

public static <T> List<T> sort(List<T> list) {
  AVLTree<T> tree = new AVLTree<>();
  for (T item : list) {
    tree.insert(item);
  }
  return tree.sort();
}
// reveal.js plugins