Complete Walkthrough of AVL Trees
Introduction
The AVL tree is a self-balancing Binary Search Tree (BST) in which there can never be more than one difference between the heights of the left and right subtrees for any given node.
Example of AVL Tree
The heights of the left and right subtrees for each node in the above-shown tree differ by less than or equal to one, indicating that the tree is AVL.
Example of a Tree that is NOT an AVL Tree:
The above tree is not AVL since the left and right subtrees for 8 and 12 have height differences higher than 1.
Why AVL Trees?
Search, max, min, insert, delete, and others (e.g. of BST operation) take O(h) time, where h is the BST height. Skewed Binary trees make these operations O(n). We can ensure an upper bound of O(log(n)) for all these operations if we keep the tree height O(log(n)) after every insertion and deletion. AVL trees are always O(log(n)) with n as the number of nodes in the tree.
AVL tree insertion example
We must rebalance the BST insert process after each insertion to keep the tree AVL.
Two fundamental procedures are available for balancing a BST without violating the BST property (keys(left) < key(root) < keys(right)).
- Right Rotation
- Left Rotation
Steps to follow for insertion
Let’s say the newly inserted node is w.
- Insert the standard BST for w.
- Beginning at w, move up and locate the first unbalanced node. Let's say z is the first unbalanced node, y is its child on the path from w to z, and x is its grandchild on the path from w to z.
- Rebalance the tree by completing the necessary rotations on the subtree whose root is z. As x, y, and z can be organized in four ways, there are four possible scenarios that must be addressed.
- Here are the four possible arrangements:
- Left child of z is y, while the left child of y is x. (Left Left Case)
- Left child of z if y and the right child of y is x. (Left Right Case)
- Right child of z is y and the right child of y is x. (Right Right Case)
- Right child of z is y and the left child of y is x. (Right Left Case)
The operations to be conducted in the above four instances are listed below. In all circumstances, we only need to rebalance the subtree rooted with z, and the entire tree gets balanced when the height of the subtree rooted with z is the same as it was prior to insertion (after appropriate rotations).
1. Left Left Case
2. Left Right Case
3. Right Right Case
4. Right Left Case
Approach
The concept is to use recursive BST insert, where after insertion, we receive bottom-up pointers to each ancestor individually. Therefore, to move up, we don't require a parent pointer. The recursive code itself ascends and visits every node that was previously inserted.
To put the concept into practice, follow the steps listed below:
- Perform the standard BST insertion.
- The newly inserted node's ancestor must be the current node. The current node's height should be updated.
- Find the current node's balance factor (left subtree height equal to the right subtree height).
- If the balance factor exceeds one, the present node is unbalanced, and we are either in the Left Left or Left Right case. Compare the newly inserted key to the key in the left subtree root to determine whether it is left left case or not.
- If the balance factor is smaller than -1, the present node is unbalanced, and we are either in the Right Right or Right-Left case. To determine whether it is the Right Right case, compare the newly inserted key to the key in the right subtree root.
The above technique is implemented as follows:
Output:
Complexity Analysis
Time Complexity: O(log(n)), For Insertion
Auxiliary Space: O(1)
Because only a few points are altered, the rotation operations (left and right rotate) take constant time. Updating the height and calculating the balance factor both take time. As a result, the AVL insert has the same time complexity as the BST insert, which is O(h), where h is the height of the tree. The height of the AVL tree is O since it is balanced (Logn). As a result, the temporal complexity of the AVL insert is O. (Logn).
Comparison with Red Black Tree
The AVL tree, as well as other self-balancing search trees such as Red Black, are handy for performing all basic operations in O(log n) time. When compared to Red-Black Trees, AVL trees are more balanced, although they may generate more rotations during insertion and deletion.
Therefore, if your application requires frequent insertions and deletions, Red Black trees should be used. And, if insertions and deletions are rare and searching is the most common activity, the AVL tree should be preferred over the Red Black Tree.