AVL Tree Algorithm
An AVL Tree is a form of binary tree, however unlike a binary tree, the worst
case scenario for a search is O(log n). The AVL data structure achieves this
property by placing restrictions on the difference in height between the
sub-trees of a given node, and re-balancing the tree if it violates these
restrictions.
AVL Tree Balance Requirements
The complexity of an AVL Tree comes from the balance requirements it enforces
on each node. A node is only allowed to possess one of three possible states
(or balance factors):
Left-High (balance factor -1)
The left-sub tree is one level taller than the right-sub tree
Balanced (balance factor 0)
The left and right sub-trees are both the same heights
Right-High (balance factor +1)
The right sub-tree is one level taller than the left-sub tree.
If the balance of a node becomes -2 (it was left high and a level was lost from
the left sub-tree) or +2 (it was right high and a level was lost from the right
sub-tree) it will require re-balancing. This is achieved by performing a
rotation about this node (see the section below on rotations).
Inserting in an AVL Tree
Nodes are initially inserted into AVL Trees in the same manner as an ordinary
binary search tree (that is, they are always inserted as leaf nodes). After
insertion, however, the insertion algorithm for an AVL Tree travels back along
the path it took to find the point of insertion, and checks the balance at each
node on the path. If a node is found that is unbalanced (that is, it has a
balance factor of either -2 or +2), then a rotation is performed (see the
section below on rotations) based on the inserted nodes position relative to
the node being examined (the unbalanced node).
NB. There will only ever be at most one rotation required after an insert
operation.
Deleting from an AVL Tree
The deletion algorithm for AVL Trees is a little more complex, as there are
several extra steps involved in the deletion of a node. If the node is not a
leaf node (that is, is has at least one child), then the node must be swapped
with either it's in-order successor or predecessor (based on availability).
Once the node has been swapped we can delete it (and have its parent pick up
any children it may have - bear in mind that it will only ever have at most one
child). If a deletion node was originally a leaf node, then it can simply be
removed.
Now, as with the insertion algorithm, we traverse back up the path to the root
node, checking the balance of all nodes along the path. If we encounter an
unbalanced node we perform an appropriate rotation to balance the node (see the
section below on rotations).
NB. Unlike the insertion algorithm, more than one rotation may be required
after a delete operation, so in some cases we will have to continue back up the
tree after a rotation.
AVL Tree Rotations
As mentioned previously, an AVL Tree and the nodes it contains must meet strict
balance requirements to maintain is O(log n) search capabilities. These
balance restrictions are maintained using various rotation functions. Below is
a diagrammatic overview of the four possible rotations that can be performed on
an unbalanced AVL Tree, illustrating the before and after states of an AVL Tree
requiring the rotation.
LL Rotation
RR Rotation
LR Rotation
RL Rotation