In our previous post(Binary Search Tree), we have discussed binary search trees. We have checked out the insertion, deletion, and find operation for a BST.
In the best-case scenario, BST can provide O(log n) complexity but in the worst-case scenario, this gives us O(n) complexity. The worst-case can happen if the input data is sorted in any order. To prevent the worst case, there are extensions that can help us maintain the binary tree balanced and get the best outcome. Some of them are,
AVL tree
Red black tree
Treap
B-tree
Today, we will discuss the height-balanced AVL tree.
AVL tree
AVL tree is an extension of the binary search tree. It has an additional field called the balance factor. After insert, delete, or modification operation, it always checks the balance factor of each node.
Based on the value of the balance factor, the tree self-balances itself.
Balance factor
The balance factor of a node in an AVL tree is the difference between the height of the left subtree and the height of the right subtree of that node. Balance factor = Height of Left Subtree — Height of Right Subtree (or inverse) The value of the balance factor should always be [-1, 0 or+1]
After the binary search tree insertion, we need to update the balance factor of each node. As we know we insert in any of the subtrees we are going to check all the way up to the parent to check if every node maintains the AVL properties. If the node is unbalanced, we need to rotate the tree to maintain the balance factor ≤ 1 and ≥ -1
1 2 3 4 5 6 7 8 9 10
privatevoidfixAVLProperties(TreeNode<T> node, T key){ TreeNode<T> item = node; while (item != null) { item.updateBalanceFactor(); if (item.isBalanced() == false) { applyRotation(item, getUnbalancedDirection(item, key)); } item = item.getParent(); } }
Unbalanced Node
The subtree can be unbalanced in 4 different ways,
Left unbalanced (LL)
Right unbalanced (RR)
Left Right unbalanced (LR)
Right unbalanced (RL)
For these use cases, we have to rotate our tree to maintain our balance properties.
Then we have to check the key, for which the node is unbalanced. We just need to check two nodes here and because to find the unbalanced direction two nodes are sufficient.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
private T getUnbalancedKey(TreeNode<T> node){ if (node == null || node.isBalanced()) { returnnull; } int count = 0; TreeNode<T> item = node; while (item != null) { if (count >= 2) { break; } if (item.getBalanceFactor() > 1) { item = item.getLeft(); } else { item = item.getRight(); } count++; } return item.getKey(); }
Driver
We can check our AVL tree using a driver method
1 2 3 4 5 6 7 8 9 10
publicclassMain{ publicstaticvoidmain(String[] args){ AVL<Integer> tree = new AVL<Integer>(); int[] array = newint[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; for (int i : array) { tree.insert(i, null); } tree.preorder(tree.getRoot(), (x) -> System.out.println(x)); } }