Goal
To avoid the binary tree becoming “a stick”, which makes the worst-case complexity of search Θ ( n ) \Theta(n) Θ(n).
Imbalance
The maximum difference of each node’s left and right subtree height.
Mathematical Representation:
For the tree
T
(
V
,
E
)
T(V,E)
T(V,E), its imbalance is defined as
m a x v ∈ V ∣ h e i g h t _ o f _ l e f t _ s u b t r e e ( v ) − h e i g h t _ o f _ r i g h t _ s u b t r e e ( v ) ∣ \underset{v\in V}{max}\left| height\_of\_left\_subtree(v) - height\_of\_right\_subtree(v) \right| v∈Vmax∣∣height_of_left_subtree(v)−height_of_right_subtree(v)∣∣
AVL Tree Definition
A binary tree with an imbalance not greater than 1.
Rotations
Operations to rebalance the binary tree.
Example:
5 5
/ \ / \
2 7 3 7
\ ----> / \
3 2 4
\
4
(Imbalance: 2) (Imbalance: 1)
Single Left Rotation (RL)
RL: Overview
// function call: RL(1)
1 3
/ \ / \
0 3 / \
/ \ ----> 1 5
2 5 / \ / \
/ \ 0 2 4 6
4 6
RL: Breakdown
Step 1: root(1) gets its right child(3)'s left child(2) as its right child
// root->right = root->right->left;
// Remark: root->elt (1) <= root->right->elt (3)
1
/ \
0 3 1 3
/ \ ----> / \ / \
2 5 0 2 (2) 5
/ \ / \
4 6 4 6
// Remark: the (2) is still there, but logically it's disintegrated from 3.
Step 2: the original root(1) becomes the original right child(3)'s left child.
// original_right->left = root;
// CANNOT use root->right since it's overwritten!
// Remark: root->elt (1) <= root->right->elt (3)
1 3 3
/ \ / \ / \
0 2 (2) 5 ----> / \
/ \ 1 5
4 6 / \ / \
0 2 4 6
.
Single right rotation (RR)
RR: Overview
// function call RR(5)
5 3
/ \ / \
3 6 / \
/ \ ----> 1 5
1 4 / \ / \
/ \ 0 2 4 6
0 2
RR: Breakdown
Step 1: root(5) gets its left child(3)'s right child(4) as its left child
// root->left = root->left->right;
// Remark: root->elt (5) >= root->left->right->elt (4)
5
/ \
3 6 5 3
/ \ ----> / \ / \
1 4 4 6 1 (4)
/ \ / \
0 2 0 2
// Remark: the (4) is still there, but logically it's disintegrated from 3.
Step 2: the original root(5) becomes the original left child(3)'s right child
// original_left->right = root;
// CANNOT use root->left since it's overwritten!
// root->left->elt (3) <= root->elt (5)
5 3 3
/ \ / \ / \
4 6 1 (4) ----> / \
/ \ 1 5
0 2 / \ / \
0 2 4 6
Double Rotation (RR-RL)
RR-RL: Overview
// function call RR-RL(1)
1 3
/ \ / \
0 5 / \
/ \ ----> 1 5
3 6 / \ / \
/ \ 0 2 4 6
2 4
RR-RL: Breakdown
Step 1: RR(root->right)
1 1
/ \ / \
0 5 0 3
/ \ ----> / \
3 6 2 5
/ \ / \
2 4 4 6
Step 2: RL(root)
1 3
/ \ / \
0 3 / \
/ \ ----> 1 5
2 5 / \ / \
/ \ 0 2 4 6
4 6
Double Rotation (RL-RR)
RL-RR: Overview
// function call RL-RR(5)
5 3
/ \ / \
1 6 / \
/ \ ----> 1 5
0 3 / \ / \
/ \ 0 2 4 6
2 4
RL-RR: Breakdown
Step 1: RL(root->left)
5 5
/ \ / \
1 6 3 6
/ \ ----> / \
0 3 1 4
/ \ / \
2 4 0 2
Step 2: RR(root)
5 3
/ \ / \
3 6 / \
/ \ ----> 1 5
1 4 / \ / \
/ \ 0 2 4 6
0 2
Checking and Balancing
As insert finishes, each node along the insertion path should be checked recursively (i.e. starting from the leaf, ending at the root) for imbalance.
// bal(Node* n) := height(n->left) - height(n->right)
Algorithm checkAndBal (Node* n)
if bal(n) > 1; // if imbalance > +1, at least an RR needed
if bal(n->left) < 0 // double rotation needed if signs disagree
rotateL(n->left);
rotateR(n);
else if bal(n) < -1 // if imbalance < -1, at least an RR needed
if bal(n->right) > 0 // double rotation needed if signs disagree
rotateR(n->right);
rotateL(n);
// nothing to be done if -1 <= imbalance <= 1
Remove in an AVL Tree
- Remove as in a binary search tree
- Rebalance if an imbalance has been created
Review: remove in a binary search tree
- Leaf node: replace with nullptr
- Only has left child: replace with left child
- Only has right child: replace with right child
- Has both left and right children:
- Replace with in-order successor
- Remove in-order successor from its original position