deletion in a binary search tree
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Deleting a node from a Binary Search Tree (BST) is more complex than insertion or search because removing a node must preserve the BST property: every node's left subtree contains only smaller keys, and every node's right subtree contains only larger keys. There are three cases to handle depending on how many children the target node has.
BST Property Recap
For every node in a BST:
- All keys in the left subtree are less than the node's key
- All keys in the right subtree are greater than the node's key
This property must be maintained after every deletion.
The Three Deletion Cases
Case 1: Node Has No Children (Leaf Node)
Simply remove the node:
Case 2: Node Has One Child
Replace the node with its only child:
Case 3: Node Has Two Children
This is the complex case. Replace the node with either:
- Its in-order successor (smallest node in the right subtree), or
- Its in-order predecessor (largest node in the left subtree)
Then delete that successor/predecessor from its original position.
Implementation in Python
Implementation in Java
Implementation in C++
Iterative Deletion
An iterative approach avoids recursion overhead:
Time and Space Complexity
| Operation | Average | Worst (Skewed Tree) |
| Search | O(log n) | O(n) |
| Delete | O(log n) | O(n) |
| Find successor | O(log n) | O(n) |
| Space (recursive) | O(log n) stack | O(n) stack |
| Space (iterative) | O(1) | O(1) |
The worst case occurs when the tree is completely unbalanced (essentially a linked list). Use self-balancing BSTs (AVL, Red-Black) for guaranteed O(log n) operations.
Common Pitfalls
- Not handling root deletion: If the deleted node is the root and has zero or one child, the root reference must be updated. Always return the (possibly new) root from the delete function.
- In-order predecessor vs successor: Both work correctly. Using the successor (min of right subtree) is more common, but using the predecessor (max of left subtree) is equally valid. Alternating between them can help keep the tree balanced.
- Forgetting to reconnect subtrees: When replacing a node with its successor, you must delete the successor from its original position. Otherwise, the successor appears twice in the tree.
- Memory leaks in C/C++: When deleting a node, free its memory. The recursive approach above handles this in the base cases for zero/one child, but the two-child case only copies the key — the actual successor node is freed in the recursive call.
- Duplicate keys: Standard BST deletion assumes unique keys. If duplicates exist, decide whether to delete all occurrences or just one, and handle accordingly.
Summary
- BST deletion has three cases: leaf node (remove), one child (replace with child), two children (replace with in-order successor then delete successor)
- The in-order successor is the smallest node in the right subtree
- Recursive implementation is cleaner; iterative avoids stack overflow for deep trees
- Average time complexity is O(log n); worst case is O(n) for skewed trees
- Use self-balancing BSTs (AVL, Red-Black) for guaranteed O(log n) deletion

