Introduction
Balancing a tree is crucial to keep searching fast. When a tree becomes uneven, it slows down operations. AVL tree rotations fix this by rearranging nodes to keep the tree balanced.
Imagine a seesaw with kids on both sides. If one side gets too heavy, the seesaw tips. To fix it, kids move around or swap places to balance it again. AVL rotations are like these moves to keep the seesaw level.
Before LL Rotation:
z
/
y
/
x
After LL Rotation:
y
/ \
x z
Before RR Rotation:
x
\
y
\
z
After RR Rotation:
y
/ \
x z
LR Rotation:
z
/
x
\
y
After LR Rotation:
y
/ \
x z
RL Rotation:
x
\
z
/
y
After RL Rotation:
y
/ \
x zclass 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, z): y = z.left T3 = y.right y.right = z z.left = T3 z.height = 1 + max(self.get_height(z.left), self.get_height(z.right)) y.height = 1 + max(self.get_height(y.left), self.get_height(y.right)) return y def left_rotate(self, z): y = z.right T2 = y.left y.left = z z.right = T2 z.height = 1 + max(self.get_height(z.left), self.get_height(z.right)) y.height = 1 + max(self.get_height(y.left), self.get_height(y.right)) return y def insert(self, root, key): if not root: return Node(key) elif key < root.key: root.left = self.insert(root.left, key) else: root.right = self.insert(root.right, key) root.height = 1 + max(self.get_height(root.left), self.get_height(root.right)) balance = self.get_balance(root) # LL if balance > 1 and key < root.left.key: return self.right_rotate(root) # RR if balance < -1 and key > root.right.key: return self.left_rotate(root) # LR if balance > 1 and key > root.left.key: root.left = self.left_rotate(root.left) return self.right_rotate(root) # RL if balance < -1 and key < root.right.key: root.right = self.right_rotate(root.right) return self.left_rotate(root) return root def pre_order(self, root): return [] if not root else [root.key] + self.pre_order(root.left) + self.pre_order(root.right) avl = AVLTree() root = None for key in [10, 20, 30, 40, 50, 25]: root = avl.insert(root, key) print(avl.pre_order(root))