Binary search trees: search, insert, delete
The BST property, the search path, how insertion order determines the shape of the tree, the three cases of deletion, the inorder successor and height analysis.
Binary search in a sorted array takes , but insertion and deletion take because they shift elements. In a linked list insertion is easy, but search is . A binary search tree (BST) tries to combine the good sides of both: as long as the tree stays short, search, insertion and deletion are .
The questions that almost certainly appear in the exam on this topic: insert in the given order and draw the tree, delete this node and draw the new tree, write the search path, is this tree a BST, what is the worst case. All of them rely on the few rules below.
The BST property
For every node x:
- every key in the left subtree of x is smaller than x,
- every key in the right subtree of x is larger than x.
In this course keys do not repeat. The most important consequence of this property: an inorder traversal gives the keys in increasing order.
We will use this tree throughout the page. The keys 50, 30, 70, 20, 40, 60, 80, 35, 45, 65 were inserted into an empty tree in this order:
50
/ \
30 70
/ \ / \
20 40 60 80
/ \ \
35 45 65
Inorder: 20 30 35 40 45 50 60 65 70 80. It is sorted, so it is a BST.
Search (find / contains)
Start at the root. If the key is smaller than the node, go left; if larger, go right; if equal, found. If you reach null, it is absent.
find 45: 50 30 40 45 found, 4 comp.
find 63: 50 70 60 65 null absent, 4 comp.
At each step you go down one level, so the cost is at most height + 1 comparisons: .
findMin always goes left (20), findMax always goes right (80). No comparison is even needed.
Insert
Descend as if searching for the new key. Where the search reaches null, create a new leaf. Insertion never moves existing nodes.
Inserting 63 into the tree above: 50 → 70 → 60 → 65 → the left of 65 is empty, so 63 goes there.
Insertion order determines the shape
The same set of keys gives very different trees with different orders:
order 1 2 3 4 5 6 7: order 4 2 6 1 3 5 7:
1 4
\ / \
2 2 6
\ / \ / \
3 1 3 5 7
\
...7 (height 6) (height 2)
The tree on the left is really a linked list (degenerate tree). Search is . The one on the right is perfectly balanced, and search is . Inserting sorted data is very common in real life (timestamps, increasing IDs), so relying on a plain BST is risky.
PITFALL · “zigzag” inputs are bad too.
10, 90, 20, 80, 30, 70is not sorted, but each element becomes the only child of the previous one. The result is again a chain, height 5. Sorted input is not required for a bad tree.
Delete (remove): three cases
First find the node to delete by searching. Then look at the number of children. Each of the three examples below starts from the original tree.
Case 1: leaf
Set the parent’s matching reference to null. Deleting 20: the left of 30 becomes null. Nothing else changes.
Case 2: one child
Skip the node: let the parent point directly to the grandchild. 60 has one child, 65. When 60 is deleted, the left of 70 becomes 65.
before: 70 after: 70
/ \ / \
60 80 65 80
\
65
The BST property is not broken: 65 was already in the left subtree of 70, and it stays there.
Case 3: two children
You cannot just remove the node, because you cannot attach two subtrees to a single parent reference. The solution: replace the node’s value with the value closest to it in sorted order. The rule used in this course is the inorder successor, that is, the smallest of the right subtree.
- Go left all the way in the right subtree and find the smallest.
- Copy that value into the node to be deleted.
- Delete that value from the right subtree. The minimum of the right subtree cannot have a left child, so this second deletion is always case 1 or 2.
Let’s delete 30. 30 has two children (20 and 40). Its right subtree is (40, 35, 45), and the smallest is 35. 35 is copied up, and the leaf 35 is deleted:
50
/ \
35 70
/ \ / \
20 40 60 80
\ \
45 65
Program output: 50(35(20,40(-,45)),70(60(-,65),80)).
Now let’s delete the root (50) in the original tree. The smallest of the right subtree: 70 → 60, 60 has no left child, so the successor is 60. 60 is copied to the root. Since the old 60 has the single child 65, the second deletion is case 2: 65 becomes the left child of 70.
60
/ \
30 70
/ \ / \
20 40 65 80
/ \
35 45
TIP · the predecessor works too. Deletion also works with the largest of the left subtree (the inorder predecessor). If the exam does not say which rule to use, use the successor and note this in your answer.
Inorder successor
The smallest key larger than x. Two cases:
- If x has a right subtree: the minimum of that subtree. In the main tree, successor(30) = 35.
- If not: go up; the first ancestor that you reach x from its left side is the successor. successor(45): 45 is the right child of 40; 40 is the right child of 30; 30 is the left child of 50. The answer is 50.
If there is no parent reference, find it by searching from the root: while searching for x, record every node where you turned left as a “candidate”; the last candidate is the successor.
static Integer successor(Node root, int x) {
Node t = root, succ = null;
while (t != null) {
if (x < t.element) { succ = t; t = t.left; }
else t = t.right;
}
return succ == null ? null : succ.element;
}
The largest key (80) has no successor. The predecessor is symmetric: the maximum of the left subtree, or the first ancestor that you reach from its right side.
Height and complexity
| Operation | Cost | Best / average | Worst |
|---|---|---|---|
| find, contains | |||
| insert | |||
| remove | |||
| findMin, findMax | |||
| inorder (whole tree) |
The height of a tree with n nodes is between and . If the keys are inserted in random order, the average depth is about , so the expected cost is . But “random” is not a guarantee. Those who want a guarantee move on to the balanced trees (AVL, red-black) of weeks 5 and 6.
Common mistakes
| Wrong idea | The truth |
|---|---|
| Checking a BST only with parent-child relations | The rule holds for the whole subtree; carry a (min, max) range |
| Insertion rearranges existing nodes | In a plain BST the new key is always a leaf |
| Taking the min of the left subtree when deleting a node with two children | The min of the right subtree (successor) or the max of the left subtree (predecessor) |
| The successor is always the right child | It is the LEFTMOST node of the right subtree; it can be on the left of the right child |
| If there is no right subtree, there is no successor | It can be an ancestor above, the first one that you reach from its left side |
| BST operations are always | ; worst case |
| Sorted input makes the BST balanced | The opposite: it produces a chain |
| An unsuccessful search does no work | It goes down to a leaf, still |
Test yourself
Exam-style questions. Solve them on paper first, then reveal the answer.
Insert the keys 45, 22, 67, 10, 30, 55, 80, 27, 60 in this order into an initially empty BST. Give the level-order traversal and the height of the result.
Show answer
45 is the root. 22 < 45 goes left, 67 goes right. 10: left of 45, left of 22. 30: right of 22. 55: left of 67. 80: right of 67.
27: 45 → 22 → 30 → left of 30. 60: 45 → 67 → 55 → right of 55.
45
/ \
22 67
/ \ / \
10 30 55 80
/ \
27 60The deepest nodes are 27 and 60, at depth 3. The height is 3.In the BST from question 1, which keys are compared when searching for 58, and how many comparisons are made?
Show answer
58 > 45 go right, 58 < 67 go left, 58 > 55 go right, 58 < 60 go left. The left child of 60 is null: the search fails.
4 comparisons. An unsuccessful search also goes down below a leaf, and its cost is O(h).
If 58 were inserted, it would go into exactly this null position, as the left child of 60.
In the BST from question 1, what are the inorder successor of 22 and the inorder successor of 30?
Show answer
22 has a right subtree (30, 27): the successor is the smallest of that subtree. Go left from 30: 27.
30 has no right subtree. Then go up: the successor is the first ancestor that you reach "from its left side". 30 is the right child of 22; 22 is the left child of 45. The answer is 45.
Check: inorder 10 22 27 30 45 55 60 67 80. After 22 comes 27, after 30 comes 45.
Starting from the BST in question 1, delete 30 (one child). Give the level-order traversal of the result.
Show answer
30 has a single child (27). When a node with one child is deleted, its child takes its place: the right reference of 22 now points to 27.
45
/ \
22 67
/ \ / \
10 27 55 80
\
60Level-order: 45 22 67 10 27 55 80 60.Starting from the BST in question 1, delete the root 45 using the inorder successor. Give the new root and the level-order traversal.
Show answer
45 has two children. Find the smallest of the right subtree: 67 → 55, 55 has no left child, so the successor is 55.
Copy 55 to the root. Then delete 55 from the right subtree: 55 has one child, 60, and 60 takes its place as the left child of 67.
55
/ \
22 67
/ \ / \
10 30 60 80
/
27Level-order: 55 22 67 10 30 60 80 27.Starting from the BST in question 1, delete 22 and then delete 45 (both with inorder successor). Give the preorder traversal of the result.
Show answer
Delete 22: it has two children. The smallest of the right subtree (30, 27) is 27. 27 is written in place of 22, and the leaf 27 is deleted. Now the children of 27 are 10 and 30.
Delete 45: the successor is 55 (as in the previous question), and 60 moves up.
55
/ \
27 67
/ \ / \
10 30 60 80Preorder: 55 27 10 30 67 60 80. The height of the tree dropped to 2.The keys 1 to 7 are inserted in increasing order into an empty BST. What is the height of the tree, and how many comparisons does an unsuccessful search for 8 make?
Show answer
Each new key is larger than all previous ones, so it always goes right. The tree becomes a chain to the right, that is, a linked list (degenerate tree).
7 nodes, 6 edges: height n - 1 = 6.
Searching for 8 compares with 1, 2, ..., 7 in turn: 7 comparisons. This is the worst case of a BST: O(n).
Give an insertion order of the keys 1 to 7 that produces a perfectly balanced BST of height 2.
Show answer
The root must be the median: 4. The root of the left subtree is the median of {1,2,3}, which is 2, and that of the right subtree is the median of {5,6,7}, which is 6.
The level-order of this tree is 4 2 6 1 3 5 7, and this order produces exactly this tree.
The condition: the root of every subtree must be inserted before the other keys in that subtree. For example, 4 6 2 7 5 3 1 also gives the same tree.
A BST has preorder traversal 40 25 10 30 60 50 70. What is its postorder traversal?
Show answer
In a BST the inorder is always the sorted list: 10 25 30 40 50 60 70. So you have the preorder + the (sorted) inorder.
A shorter way: insert in preorder order into an empty BST and you get the same tree. 40 is the root, 25 and 10 go left, 30 goes to the right of 25, 60 goes right, 50 and 70 are the children of 60.
Postorder: 10 30 25 50 70 60 40.
Is the binary tree below a valid BST? Explain.
50
/ \
30 70
/ \ /
20 55 60Show answer
If each node is compared only with its own children, it looks valid: 30 < 55, 20 < 30, 60 < 70.
But the BST property must hold for the whole subtree: every key in the left subtree of 50 must be smaller than 50. 55 breaks this rule.
The correct check carries a (min, max) range down to each node: for 55 the range is (30, 50), and 55 is outside this range.
How many structurally different BSTs can be formed with the keys 1, 2, 3? With 1, 2, 3, 4?
Show answer
Choose the root, and build the left and the right independently. , ., , .. These are the Catalan numbers.
3 keys have 6 insertion orders, but 2 1 3 and 2 3 1 give the same tree, so there are 5.
Give the worst-case and the average-case time of search, insert and delete in a BST with n nodes (random insertion order). What determines the cost?
Show answer
All three operations go down along one path from the root, and the length of the path is at most the height h. The cost is O(h).
With random insertion order the average node depth is about : O(log n).
Sorted or nearly sorted input produces h = n - 1: O(n). That is why in week 5 we move on to balanced trees such as AVL.
Verification: The trees produced by all insertion sequences, search paths, trees after deletion (inorder successor for two children), successor/predecessor values, heights and the counts of distinct BST shapes were computed with Java (verify/SEN2212/W03.java, java W03.java).