3.4.7 · Coding › Trees
Ek plain Binary Search Tree (BST) linked list mein degenerate ho sakta hai (1,2,3,4,5 order mein insert karo → height n → O ( n ) search). Ek AVL tree ek aisa BST hai jo har insert/delete ke baad apni shape khud theek karta hai taaki uski height O ( log n ) rahe. Poora trick yeh hai: change ke baad, upar ki taraf walk karo; pehla node jis ka left/right height 1 se zyada differ kare, use rotation milti hai jo use re-balance karti hai. Kaun si rotation — yeh master kar lo, AVL master ho jayega.
Ek self-balancing Binary Search Tree jisme, har node ke liye, balance factor satisfy karta hai ∣ B F ∣ ≤ 1 . Naam rakha gaya inventors Adelson-Velsky and Landis (1962) ke naam par.
Definition Balance factor (BF)
B F ( n o d e ) = h e i g h t ( n o d e . l e f t ) − h e i g h t ( n o d e . r i g h t )
Convention ke according ek empty subtree ki height − 1 hoti hai aur ek single leaf ki height 0 hoti hai.
Allowed values: ==− 1 , 0 , + 1 ==. Isse bahar kuch bhi ho matlab node unbalanced hai aur rotation chahiye.
B F = + 2 → left-heavy (problem left mein hai)
B F = − 2 → right-heavy (problem right mein hai)
Intuition Balancing height ko logarithmic kyun rakhti hai
Agar height h ka sabse worst (sparsest) AVL tree bhi bahut saare nodes contain karta hai, toh n nodes wala koi bhi tree bahut lamba nahi ho sakta. Isliye hum minimum number of nodes N ( h ) dhundte hain height-h AVL tree mein.
Ek rotation ek local re-pointering of 3 nodes hai jo BST in-order ordering preserve karti hai jabki height reduce karti hai. Imbalance ki shape batati hai kaun si rotation lagani hai.
Maano z = upar jaate waqt pehla unbalanced node, y = uska taller child, x = y ka taller child.
Case
Shape
Fix
LL
z left-heavy, y ke left mein insert hua
z par ek right rotation
RR
z right-heavy, y ke right mein insert hua
z par ek left rotation
LR
z left-heavy, y ke right mein insert hua
y par left, phir z par right
RL
z right-heavy, y ke left mein insert hua
y par right, phir z par left
Definition AVL insert (recursive)
Normal BST insert karo (recurse, leaf place karo).
Wapas upar jaate waqt, update_height(node).
BF compute karo. Agar |BF|>1, toh BF aur key se case identify karo, rotate karo.
def insert (node, key):
if node is None : return Node(key)
if key < node.key: node.left = insert(node.left, key)
elif key > node.key: node.right = insert(node.right, key)
else : return node # no duplicates
update_height(node)
bf = balance(node)
# LL
if bf > 1 and key < node.left.key: return rotateRight(node)
# RR
if bf < - 1 and key > node.right.key: return rotateLeft(node)
# LR
if bf > 1 and key > node.left.key:
node.left = rotateLeft(node.left); return rotateRight(node)
# RL
if bf < - 1 and key < node.right.key:
node.right = rotateRight(node.right); return rotateLeft(node)
return node
Key fact: ek insert ko har jagah balance restore karne ke liye at most EK rotation (single ya double) chahiye.
Standard BST delete (leaf → remove; ek child → splice; do children → in-order successor se replace karo, phir woh successor delete karo).
Wapas upar walk karo, heights update karo.
BF se rebalance karo — lekin yahan case decide karo children ke BF se, key se nahi:
bf = balance(node)
if bf > 1 :
if balance(node.left) >= 0 : return rotateRight(node) # LL
else : node.left = rotateLeft(node.left); return rotateRight(node) # LR
if bf < - 1 :
if balance(node.right) <= 0 : return rotateLeft(node) # RR
else : node.right = rotateRight(node.right); return rotateLeft(node) # RL
Insert se difference: ek delete multiple levels par rotations trigger kar sakta hai (up to O ( log n ) tak), kyunki ek node ko fix karna subtree ko chhota kar sakta hai aur ancestor ko unbalance kar sakta hai.
Worked example Example 1 — LL case (30, 20, 10 insert karo)
30 insert karo → root.
20 insert karo → 30 ke left mein. BF(30)=0 − ( − 1 ) = 1 . OK.
10 insert karo → 20 ke left mein. Ab BF(30)=1 − ( − 1 ) = 2 → unbalanced, left-heavy.
Yeh step kyun? 10 < 20 (left child ki key), isliye naya node left ke left mein gaya → LL → 30 par single right rotation .
Result: 20 root hai, 10 left, 30 right. Balanced, height 1. ✅
Worked example Example 2 — LR case (30, 10, 20 insert karo)
30 root; 10 left of 30; 20 → right of 10.
BF(30)=1 − ( − 1 ) = 2 (left-heavy) lekin 20 > 10 → left ke right mein gaya → LR .
Yeh step kyun? Zig-zag (left phir right) ko pehle seedha karna padta hai.
Step A: rotateLeft(10) → subtree 20 over 10 ban jata hai. Ab yeh clean LL hai.
Step B: rotateRight(30) → 20 root, 10 left, 30 right . ✅
Do rotations kyun? Ek rotation bent path fix nahi kar sakti; inner wali use straight karti hai.
Worked example Example 3 — delete par RL
Tree: 50(root), 30 left, 70 right, 60 left-of-70. 30 delete karo.
BF(50)=h e i g h t ( L ) − h e i g h t ( R ) = ( − 1 ) − ( 1 ) = − 2 → right-heavy.
Yeh step kyun? 30 hatne ke baad right side zyada lamba ho gaya.
balance(70) check karo: uska left (60) taller hai → B F ( 70 ) = + 1 > 0 → RL case.
rotateRight(70) → 60 over 70; phir rotateLeft(50) → 60 root, 50 left, 70 right . ✅
Common mistake Empty subtree ki height
− 1 bhoolna
Galat idea kyun sahi lagta hai: log empty height 0 set karte hain "kyunki kuch nahi hai." Fix: empty = − 1 ke saath, ek leaf ko height 0 milti hai aur BF formulas clean nikalta hai (B F of leaf = 0 ). 0 use karne se har BF ek se shift ho jaata hai aur detection break ho jaati hai.
Common mistake Heights top-down ya sirf root par update karna
Kyun sahi lagta hai: "Maine root change kiya, toh root update karo." Fix: rotation ke baad lower node ki bhi height change hoti hai . Hamesha update_height(child) pehle karo, update_height(parent) ke pehle, aur poore path par upar tak update karo.
Common mistake Rotation nodes count se choose karna, BF/key se nahi
Kyun sahi lagta hai: tree lopsided dikhta hai . Fix: rule use karo: B F ( z ) ka sign batata hai left/right-heavy; key (insert) ya child ka BF (delete) batata hai straight vs bent → exactly ek LL/RR/LR/RL.
Common mistake Yeh assume karna ki delete ko at most ek rotation chahiye
Kyun sahi lagta hai: insert ko sirf ek hi chahiye. Fix: delete cascade kar sakta hai — root tak har ancestor ko rebalance karte raho.
Recall Feynman: 12 saal ke bachche ko explain karo
Socho blocks ka ek tower jisme har block ke left aur right stack almost same height hone chahiye — kabhi bhi ek se zyada off nahi. Jab bhi koi block add ya remove karo, us jagah se upar tak check karo: agar ek side bahut zyada lamba ho gaya, toh tower ko thoda tilt karo (ek rotation) taaki woh wapas balanced ho jaye. Kyunki yeh kabhi zyada nahi jhukata, tum hamesha koi bhi block sirf kuch levels neeche jaake dhundh sakte ho — fast! "Tilt" 4 tarah ke aate hain depending on kaun si side bahut lamba hua aur kya seedha jhukav hai ya zig-zag jhukav hai.
Mnemonic Char cases yaad karne ka tarika
"Same letters = single, mixed letters = double."
LL, RR (matching) → ek rotation (chhoti side ki taraf rotate karo).
LR, RL (mixed) → do rotations; pehla letter kehta hai "child par woh rotation karo," doosra letter parent ki fix hai.
Yeh bhi: "heavy side ke opposite rotate karo." Left-heavy → right rotate karo.
Kisi node ka balance factor kya hota hai? h e i g h t ( l e f t ) − h e i g h t ( r i g h t ) , allowed values − 1 , 0 , + 1 .
Empty subtree ko kaunsi height assign ki jaati hai? − 1 (isliye ek leaf ki height 0 hoti hai).
LL imbalance kaun si rotation fix karti hai? Unbalanced node par ek single right rotation.
LR case fix? rotateLeft(child) phir rotateRight(node).
RL case fix? rotateRight(child) phir rotateLeft(node).
Insert par LL aur LR mein fark kaise pehchante hain? Dono left-heavy hain (B F = + 2 ); key ko left child ki key se compare karo — chhota=LL, bada=LR.
Ek AVL insert ke baad max kitni rotations chahiyen? Ek (single ya double).
Delete ko kaafi rotations kyun chahiyen? Ek rotation subtree ko chhota kar sakti hai, ancestor ko unbalance kar sakti hai, isliye root tak rebalance karo.
Height-h AVL tree ke minimum nodes kaunsa recurrence deta hai? N ( h ) = 1 + N ( h − 1 ) + N ( h − 2 ) — ek shifted Fibonacci, N ( h ) = F h + 3 − 1 .
n ke terms mein worst-case AVL height?≈ 1.44 log 2 n = O ( log n ) .
Rotation par kaunse node ki height pehle update karo? Lower (child) node ki, phir parent ki.
AVL mein search/insert/delete ki time complexity? O ( log n ) har ek.
Binary Search Tree — AVL ek BST hai plus balance invariant.
Tree Rotations — woh shared primitive jo AVL aur Red-Black Tree dono use karte hain.
Red-Black Tree — looser balancing (height ≤ 2 log n ), delete par kam rotations.
Fibonacci Numbers — minimum node count / height ko bound karta hai.
Big-O Notation — O ( log n ) height kyun matter karti hai.
Heap vs AVL — dono balanced hain, lekin heaps sirf parent-child order karte hain, full in-order nahi.
BF = +2 left-heavy or -2 right-heavy
Fibonacci recurrence gives
Balance Factor = hleft - hright
N of h = 1 + N h-1 + N h-2