AVL Tree: Definition, How It Works, and When to Use
AVL tree is a type of self-balancing binary search tree where the difference in height between left and right subtrees is at most one for every node. This balance ensures operations like search, insert, and delete run efficiently in O(log n) time.How It Works
An AVL tree keeps itself balanced by making sure the heights of the left and right branches of every node differ by no more than one. Imagine a tree where branches grow evenly so it doesn’t lean too much to one side. This balance helps the tree stay efficient for searching and updating data.
When you add or remove a value, the tree checks if it became unbalanced. If it did, it performs simple rotations—like gently turning branches—to restore balance. These rotations keep the tree’s height as small as possible, which means finding or changing data stays fast.
Example
This example shows how to insert values into an AVL tree and keep it balanced automatically.
class Node: def __init__(self, key): self.key = key self.left = None self.right = None self.height = 1 class AVLTree: def get_height(self, node): return node.height if node else 0 def get_balance(self, node): return self.get_height(node.left) - self.get_height(node.right) if node else 0 def right_rotate(self, y): x = y.left T2 = x.right x.right = y y.left = T2 y.height = 1 + max(self.get_height(y.left), self.get_height(y.right)) x.height = 1 + max(self.get_height(x.left), self.get_height(x.right)) return x def left_rotate(self, x): y = x.right T2 = y.left y.left = x x.right = T2 x.height = 1 + max(self.get_height(x.left), self.get_height(x.right)) y.height = 1 + max(self.get_height(y.left), self.get_height(y.right)) return y def insert(self, node, key): if not node: return Node(key) if key < node.key: node.left = self.insert(node.left, key) else: node.right = self.insert(node.right, key) node.height = 1 + max(self.get_height(node.left), self.get_height(node.right)) balance = self.get_balance(node) # Left Left if balance > 1 and key < node.left.key: return self.right_rotate(node) # Right Right if balance < -1 and key > node.right.key: return self.left_rotate(node) # Left Right if balance > 1 and key > node.left.key: node.left = self.left_rotate(node.left) return self.right_rotate(node) # Right Left if balance < -1 and key < node.right.key: node.right = self.right_rotate(node.right) return self.left_rotate(node) return node def pre_order(self, root): return ([root.key] + self.pre_order(root.left) + self.pre_order(root.right)) if root else [] # Usage avl = AVLTree() root = None values = [10, 20, 30, 40, 50, 25] for v in values: root = avl.insert(root, v) print(avl.pre_order(root))
When to Use
Use an AVL tree when you need fast search, insert, and delete operations and want to keep data sorted. It is especially useful when your data changes often and you want to avoid slow operations caused by unbalanced trees.
Real-world uses include databases, file systems, and memory management where quick data access and updates are critical. AVL trees guarantee that these operations stay efficient by maintaining balance automatically.
Key Points
- An AVL tree is a self-balancing binary search tree.
- It keeps the height difference between left and right subtrees at most one.
- Rotations fix imbalances after insertions or deletions.
- Operations like search, insert, and delete run in O(log n) time.
- Ideal for applications needing fast, balanced data access.