2. 2
Trees and balance
• balanced tree: One whose subtrees differ in height by at most 1 and
are themselves balanced.
A balanced tree of N nodes has a height of ~ log2 N.
A very unbalanced tree can have a height close to N.
The runtime of adding to / searching a
BST is closely related to height.
Some tree collections (e.g. TreeSet)
contain code to balance themselves
as new nodes are added.
19
7
14
6
9
8
4
root
height = 4
(balanced)
3. 3
Some height numbers
• Observation: The shallower the BST the better.
Average case height is O(log N)
Worst case height is O(N)
Simple cases such as adding (1, 2, 3, ..., N), or the opposite order,
lead to the worst case scenario: height O(N).
• For binary tree of height h:
max # of leaves: 2h-1
max # of nodes: 2h
- 1
min # of leaves: 1
min # of nodes:h
21
18
20
8
15
14
2
root
4. 4
Calculating tree height
• Height is max number of nodes in path from root to any leaf.
height(null) = 0
height(a leaf) = ?
height(A) = ?
Hint: it's recursive!
height(a leaf) = 1
height(A) = 1 + max(
height(A.left), height(A.right))
A
A.left A.right
5. 5
AVL trees
• AVL tree: a binary search tree that uses modified add and remove
operations to stay balanced as its elements change
one of several kinds of auto-balancing trees (others in book)
invented in 1962 by two Russian mathematicians
• (Adelson-Velskii and Landis)
• A-V & L proved that an AVL tree's height is always O(log N).
basic idea: When nodes are added to / removed from the tree,
if the tree becomes unbalanced, repair the tree until balance is
restored.
• rebalancing operations are relatively efficient (O(1))
• overall tree maintains a balanced O(log N) height, fast to add/search
6. 6
Balance factor
• balance factor, for a tree node T :
= height of T's right subtree minus height of T's left subtree.
BF(T) = Height(T.right) - Height(T.left)
• (the tree at right shows BF of each node)
an AVL tree maintains a "balance factor"
in each node of 0, 1, or -1
• i.e. no node's two child subtrees
differ in height by more than 1
it can be proven that the height of an
AVL tree with N nodes is O(log N)
-2
3 1
-1
-2
0
0
7. 7
AVL tree examples
• Two binary search trees:
(a) an AVL tree
(b) not an AVL tree (unbalanced nodes are darkened)
8. 8
Tracking subtree height
• Many of the AVL tree operations depend on height.
Height can be computed recursively by walking the tree; too slow.
Instead, each node can keep track of its subtree height as a field:
20
9
2 15
5
10
30
7
1
1
1
1
2
3 2
4
10
4
data
height
left/
right
9. 9
AVL add operation
• For all AVL operations, we assume the tree was balanced before the
operation began.
Adding a new node begins the same as with a typical BST, traversing
left and right to find the proper location and attaching the new node.
But adding this new node may unbalance the tree by 1:
set.add(49);
87
29
55
42
-3
49
10. 10
Key idea: rotations
• If a node has become out of balanced in a given direction, rotate it
in the opposite direction.
rotation: A swap between parent and left or right child,
maintaining proper BST ordering.
8
25
3
rotate right
8
25
3
11 11
11. 11
Right rotation steps
1. Detach left child (11)'s right subtree (27) (don't lose it!)
2. Consider left child (11) be the new parent.
3. Attach old parent (43) onto right of new parent (11).
4. Attach new parent (11)'s old right subtree (27)
as left subtree of old parent (43).
11
43
8 27
65
3
11
43
8
27 65
3
11
43
8 27
65
3
12. 12
Right rotation code
private TreeNode rightRotate(TreeNode oldParent) {
// 1. detach left child's right subtree
TreeNode orphan = oldParent.left.right;
// 2. consider left child to be the new parent
TreeNode newParent = oldParent.left;
// 3. attach old parent onto right of new parent
newParent.right = oldParent;
// 4. attach new parent's old right subtree as
// left subtree of old parent
oldParent.left = orphan;
oldParent.height = height(oldParent); // update nodes'
newParent.height = height(newParent); // height values
return newParent;
}
13. 13
Left rotation steps
1. Detach right child (65)'s left subtree (51) (don't lose it!)
2. Consider right child (65) be the new parent.
3. Attach old parent (43) onto left of new parent (65).
4. Attach new parent (65)'s old left subtree (51)
as right subtree of old parent (43).
65
43
87
51
21
73
21
43
65
51 87
73
65
87
43
73
21 51
14. 14
Left rotation code
private TreeNode leftRotate(TreeNode oldParent) {
// 1. detach right child's left subtree
TreeNode orphan = oldParent.right.left;
// 2. consider right child to be the new parent
TreeNode newParent = oldParent.right;
// 3. attach old parent onto left of new parent
newParent.left = oldParent;
// 4. attach new parent's old left subtree as
// right subtree of old parent
oldParent.right = orphan;
oldParent.height = height(oldParent); // update nodes'
newParent.height = height(newParent); // height values
return newParent;
}