6.6 AVL balanced trees and Balancing algorithm
An AVL tree is a self-balancing binary search tree (BST) where the heights of the two child subtrees of any node differ by at most one. It is named after its inventors, Adelson-Velsky and Landis. AVL trees are designed to maintain a balanced structure, ensuring that the height of the tree remains O(log n) where n is the number of nodes in the tree.
Definition:
In an AVL tree:
Why AVL Tree:
The main motivation behind using AVL trees is to ensure that the operations performed on the tree (insertion, deletion, and search) have a guaranteed time complexity of O(log n), where n is the number of nodes in the tree. Without balancing, in a typical binary search tree, the tree could degenerate into a linked list in the worst case scenario, leading to linear time complexity (O(n)) for these operations.
By maintaining the balance property, AVL trees provide faster search times compared to unbalanced binary search trees. This balance ensures that the height of the tree remains relatively small, optimizing the time complexity of operations. Additionally, AVL trees are particularly useful in scenarios where the tree is frequently updated, as their self-balancing property helps in maintaining efficiency even after numerous insertions and deletions.
Overall, AVL trees strike a balance between the efficiency of operations and the overhead of maintaining balance, making them a popular choice for applications where fast search times are crucial and the dataset is subject to frequent modifications.
Balance Factor
The balance factor of a node in an AVL tree is calculated as the difference between the height of its left subtree and the height of its right subtree. Mathematically, the balance factor (BF) of a node can be expressed as:
BF=height of left subtree−height of right subtree
In this formula, "height of left subtree" refers to the height of the left child subtree of the node, and "height of right subtree" refers to the height of the right child subtree of the node.
The balance factor can take on three possible values:
For a balanced AVL tree, the balance factor of every node must be either -1, 0, or 1. If the balance factor of any node violates this condition, the tree needs to be rebalanced to maintain AVL tree properties.
Every AVL Tree is a binary search tree but every Binary Search Tree need not be AVL tree.
Rotation Operation in AVL Tree
AVL tree rotations are operations performed on AVL trees to maintain the balance property after an insertion or deletion that may have caused the tree to become unbalanced. In an AVL tree, balance is maintained by ensuring that the heights of the left and right subtrees of any node differ by at most one. When this balance condition is violated, rotations are performed to restore balance without violating the binary search tree property.
There are four main types of AVL tree rotations:
Left Rotation (LL Rotation):
Right Rotation (RR Rotation):
Left-Right Rotation (LR Rotation):
Right-Left Rotation (RL Rotation):
SEARCH IN AVL TREE
In a balanced AVL tree, the height of the tree is guaranteed to be O(log n), where n is the number of nodes in the tree. This balanced height ensures that the search operation has a time complexity of O(log n) in the average and worst-case scenarios.
The reason for this time complexity is that at each level of the tree, the search space is effectively halved due to the balanced structure. Therefore, with each comparison, the search effectively eliminates half of the remaining nodes, leading to a logarithmic time complexity with respect to the number of nodes in the tree.
Algorithm:
Algorithm: AVL Tree Search
Step 1: Read the search element from the user.
Step 2: Call AVL_SEARCH(root, search_element).
Step 3: END.
Procedure AVL_SEARCH(node, search_element):
Step 1: If node is NULL, return "Element is not found".
Step 2: If search_element is equal to node -> DATA, then display "Given node is found!!!" and terminate.
Step 3: If search_element is less than node -> DATA, then call AVL_SEARCH(node -> LEFT, search_element).
Step 4: If search_element is greater than node -> DATA, then call AVL_SEARCH(node -> RIGHT, search_element).
Insertion Operation in AVL Tree
In an AVL tree, the insertion operation is performed with O(log n) time complexity. In AVL Tree, a new node is always inserted as a leaf node. The insertion operation is performed as follows.
Algorithm:
Algorithm: AVL Tree Insertion
Step 1: Insert the new element into the tree using Binary Search Tree insertion logic.
Step 2: Call AVL_CHECK_BALANCE(root).
Step 3: END.
Procedure AVL_CHECK_BALANCE(node):
Step 1: If node is NULL, return.
Step 2: Calculate the balance factor (BF) of the node.
Step 3: If the balance factor (BF) of the node is -1, 0, or 1, continue to the next node.
Step 4: If the balance factor (BF) of the node is other than -1, 0, or 1, the tree is imbalanced.
Step 5: Perform suitable rotation(s) to rebalance the tree.
Step 6: Call AVL_CHECK_BALANCE(node -> LEFT) recursively.
Step 7: Call AVL_CHECK_BALANCE(node -> RIGHT) recursively.
Example: Construct an AVL Tree by inserting numbers from 1 to 8.
Deletion Operation in AVL Tree
The deletion operation in AVL Tree is similar to the deletion operation in Binary Search Tree. But after every deletion operation, we need to check with the Balance Factor condition. If the tree is balanced after deletion go for the next operation otherwise perform suitable rotation to make the tree Balanced.