Search, Insert, Delete
Searching is a walk: compare with the current node, go left if smaller, right if larger, stop when equal or when you fall off the tree. Insertion follows the same walk and attaches the new node where the search failed.
Deletion is the fiddly one, with three cases:
- Leaf — just remove it.
- One child — the child takes its place.
- Two children — replace the value with its in-order successor (the smallest value in the right subtree), then delete that successor. Only this choice preserves the BST rule.
In-Order Traversal Sorts For Free
Visit left subtree, then the node, then the right subtree. Because of the BST rule, this emits every value in ascending sorted order — press In and read the output.
The other two orders have their own uses: pre-order (node first) is how you copy or serialise a tree, and post-order (node last) is how you delete one safely, since children are freed before their parent.
The Fatal Weakness
Press Sorted input. Inserting already-sorted values means every new value is larger than everything before it, so it always goes right. The tree becomes a single downward chain — a linked list wearing a tree costume.
Height goes from O(log n) to O(n), and every operation degrades with it. This is not a rare edge case: inserting sorted data is extremely common in practice.
Which Is Why Self-Balancing Trees Exist
AVL trees and red-black trees detect when a subtree grows lopsided and perform rotations to restore balance, guaranteeing O(log n) regardless of insertion order. Red-black trees are what back std::map in C++ and TreeMap in Java.
Compare the height readout after pressing Balanced versus Sorted input with the same values — the gap is exactly what balancing buys.
BST or Hash Table?
A hash table is faster for pure lookup — O(1) versus O(log n). But a BST keeps its data ordered, which a hash table cannot. Use a tree when you need sorted iteration, range queries ("all values between 20 and 50"), or nearest-neighbour lookups. Use a hash table when you only ever ask "is this exact key present?".
The degenerate case
Insert 1, 2, 3, 4, 5 into an empty BST in that order and every node becomes the right child of the last. The tree is a linked list, and every operation is O(n).
Sorted input produces the worst possible tree. That is not a rare pathological case — inserting records in id order, or in date order, is entirely normal.
Three responses:
Self-balancing trees. AVL and red-black trees rotate on insertion to keep the height O(log n) automatically. This is what production implementations use.
Randomised insertion order, if you control it. Expected height O(log n).
A different structure. A sorted array with binary search, or a skip list, or a B-tree for disk-based data.
| Tree | Balance rule | Character |
|---|
| AVL | Heights differ by at most 1 | Strictly balanced; faster lookups |
| Red-black | Colour rules bound the height | Fewer rotations; faster insertion |
| B-tree | Many keys per node | Designed for disk pages |
| Treap | Random priorities | Simple, probabilistic balance |
Red-black trees are what most standard libraries use for ordered maps — C++'s std::map, Java's TreeMap — because they balance insertion and lookup cost well.
Guided tour
- Insert a few values and watch each one walk down the tree, going left or right at every comparison.
- Search for something. The highlighted path shows roughly half the remaining tree being discarded at each step.