Binary Search Tree (BST) — BST property, insert, search, delete (3 cases)
WHY does the BST property exist?
WHAT we want: a data structure that supports search, insert, delete all fast (ideally ), while staying dynamic (sizes change).
- A sorted array gives search (binary search) but insert/delete (shifting).
- A linked list gives insert but search.
WHY the property helps: If we keep the invariant "left < node < right", then at any node we can decide a direction by one comparison. Going left or right discards an entire subtree. If the tree is balanced, depth is , so all operations cost .

Search — derive it from the property
def search(node, t):
while node is not None:
if t == node.key:
return node
node = node.left if t < node.key else node.right
return None # not presentWhy this step? Each comparison uses the invariant to eliminate one whole subtree, so we follow a single root-to-leaf path. Cost = path length = where = height.
Insert — search, then attach at the empty spot
def insert(root, v):
if root is None:
return Node(v)
if v < root.key:
root.left = insert(root.left, v)
elif v > root.key:
root.right = insert(root.right, v)
# v == root.key: duplicate, ignore (or handle as you like)
return rootWhy this step? We descend exactly like search, preserving the invariant on the way down. New nodes are always inserted as leaves, so no existing relationships break. Cost .
Delete — the 3 cases (the heart of BSTs)
First find the node. Then handle by number of children.
def find_min(node): # leftmost node
while node.left is not None:
node = node.left
return node
def delete(root, v):
if root is None:
return None
if v < root.key:
root.left = delete(root.left, v)
elif v > root.key:
root.right = delete(root.right, v)
else: # found node to delete
if root.left is None: # Case 1 & 2 (no left child)
return root.right
if root.right is None: # Case 2 (no right child)
return root.left
succ = find_min(root.right) # Case 3: in-order successor
root.key = succ.key # copy successor key up
root.right = delete(root.right, succ.key) # delete successor
return rootWhy this step?
return root.rightwhen no left child cleanly covers leaf (both None → returns None) and one-child cases. Elegant unification.- In Case 3 the successor is the leftmost node of the right subtree, so it has no left child → deleting it is always Case 1 or 2. The recursion can never loop forever.
Steel-manning the BST-validation mistake
Active recall
Recall Predict before peeking
- Why does going left/right discard half the work?
- Where is a newly inserted key always placed?
- Why is the in-order successor guaranteed to have ≤ 1 child?
- What's the worst-case height and when does it happen?
Answers: (1) the invariant guarantees the target can only be on one side; (2) as a leaf; (3) it's the leftmost node of the right subtree, so it has no left child; (4) , when keys are inserted in sorted/reverse-sorted order (degenerate stick).
Recall Feynman: explain to a 12-year-old
Imagine a guessing game where numbers are kept on shelves. Every shelf has a number. Smaller numbers go on the shelf to the left, bigger ones to the right — and this rule repeats for every shelf. To find a number you start at the top and keep asking "is it smaller or bigger?", stepping left or right. Each step you skip a whole pile of shelves, so you find it super fast. To remove a shelf that has two shelves hanging off it, you sneak in the next-bigger number from the right side to take its place, because that's the only number that keeps everyone in the right order.
Flashcards
What is the BST property (state it precisely)?
What traversal of a BST yields sorted order?
Why is BST search and not guaranteed?
Where is a new key inserted in a BST?
Delete Case 1 (leaf)?
Delete Case 2 (one child)?
Delete Case 3 (two children)?
Why must the successor in Case 3 have at most one child?
Why doesn't checking only direct children validate a BST?
When does a BST degenerate to operations?
In-order successor of a node with a right subtree is found how?
Connections
- Binary Tree — terminology & traversals (in-order is the BST sorted walk)
- Binary Search on Sorted Array (same halving idea, static data)
- AVL Tree and Red-Black Tree (self-balancing fix for degenerate BSTs)
- Tree Height vs Depth (why drives all costs)
- Heap vs BST (heap orders parent–child by priority, not left/right by value)
- Recursion on Trees (delete/insert as return-the-subtree pattern)
Concept Map
Hinglish (regional understanding)
Intuition Hinglish mein samjho
BST ka basic funda ek hi line mein: har node ke left mein chhote, right mein bade keys. Aur yeh rule sirf direct children ke liye nahi, poore subtree ke liye chalta hai (recursively). Isi wajah se jab tum kisi key ko dhoondhte ho, har node pe sirf ek comparison karke aadha tree foran phenk dete ho — bilkul binary search jaisa, par yahan insert/delete bhi sasta hai.
Search simple hai: root se start karo, target chhota hai toh left jao, bada hai toh right, milne tak ya None aane tak. Insert bhi search hi hai — jahan search "gir jaata hai" (None slot), wahin naya leaf laga do, isse purane connections kabhi nahi tootte. Ek important baat: agar keys sorted order mein insert karoge toh tree ek seedhi line (stick) ban jaayega aur sab kuch ho jaayega — isi problem ka solution AVL/Red-Black trees hain.
Delete mein 3 cases yaad rakho: (1) leaf ho toh seedha kaat do; (2) ek child ho toh us child ko parent se direct jod do (lift kar do); (3) do children ho toh node ki value ko uske in-order successor (right subtree ka sabse chhota) se replace karo, phir us successor ko delete karo — wo successor hamesha leftmost hota hai isliye uska left child nahi hota, matlab wo Case 1 ya 2 mein simat jaata hai. Yeh trick order ko intact rakhti hai.
Ek classic galti: log socht hain "bas node vs uske do children check kar lo, BST valid hai" — galat! Door ka ancestor violate ho sakta hai. Sahi tareeka hai har node ko ek range (low, high) ke andar check karna. Yaad rakho: "Left-Less, Right-Right" aur delete ke liye "0 = cut, 1 = lift, 2 = swap-with-successor."