Exercises — Module 07 (Searching)
Self-contained problems on this module's material — binary search and its comparison bound, binary search trees and their random-input analysis, Hibbard deletion, AVL height via Fibonacci trees, and the hashing analyses (linear probing vs. uniform/double hashing). You can work every one without the books: each states the problem in full, gives a hint to peek at when stuck, and a worked answer sketch to check against after you try. Computational answers here are reproduced by the code you write in the lab (or a few lines at a REPL).
Ratings follow Knuth's scale (00–50; M = needs mathematics, ▶ = especially
instructive). Where a problem mirrors a TAOCP exercise its number is noted for
readers who own Volume 3.
Tracking
| # | Topic | Rating | Status |
|---|---|---|---|
| 1 | Hand-trace Algorithm B and count comparisons | 10 | ⬜ |
| 2 | ▶ Prove Theorem B (comparison-tree bound) | 22 | ⬜ |
| 3 | An inorder traversal of a BST is sorted | 20 | ⬜ |
| 4 | ▶ Random-BST average search cost | 26 | ⬜ |
| 5 | Hibbard deletion is not randomness-preserving | 30 | ⬜ |
| 6 | ▶ AVL height bound via Fibonacci trees; tightness | 25 | ⬜ |
| 7 | Linear-probing successful-search analysis | 22 | ⬜ |
| 8 | ▶ Double vs. uniform hashing; secondary clustering | 28 | ⬜ |
Problems
1. Hand-trace Algorithm B and count comparisons (rating 10 · cf. 6.2.1-1)
Problem. The sixteen keys, sorted, are
Trace Algorithm B (binary search: , ; repeatedly compare against with , narrowing to the correct half) searching for . List the successive and count the comparisons. Then do the same for the absent key .
Hint. Each pass makes one three-way comparison and moves either or . The search fails when .
Answer sketch. For : pass 1 , , ; pass 2 , , ; pass 3 , , ; pass 4 , , equal — found at index 7 in 4 comparisons. For : it compares against (also 4 comparisons), then fires and it reports "absent" with insertion point (four keys are ). (Verified by direct simulation: 503 → 4 comparisons at index 7; 400 → 4 comparisons, not found.) Both stay within Theorem B's ceiling .
2. ▶ Prove Theorem B (comparison-tree bound) (rating 22 · cf. 6.2.1-3)
Problem. Prove Theorem B: Algorithm B makes at most comparisons on an array of keys, whether the search succeeds or fails.
Hint. Model the algorithm as a binary comparison tree: internal nodes (one per key, where a successful search stops) and external nodes (the gaps where an absent key lands). Because Algorithm B always halves the live range, how deep can an internal node be?
Answer sketch. Draw the tree of comparisons: the root compares against , its children handle the two halves, recursively. This binary tree has internal nodes and external nodes. Since each pass makes the range as even as possible, halving every step, an internal node at "level " (root = level 0) governs a subrange of size at most ; the deepest internal node has level . A successful search stops at an internal node, costing at most comparisons (levels through ). An unsuccessful search descends to an external node one level deeper, but its last actual comparison happened at the internal parent, so the count is the same bound. Hence either way. (Check: bound , and the traces of Problem 1 used .)
3. An inorder traversal of a BST is sorted (rating 20 · cf. 6.2.2-5)
Problem. A binary search tree stores keys so that for every node , all keys in 's left subtree are and all in its right subtree are . Prove that a symmetric (inorder) traversal — left subtree, then node, then right subtree — visits the keys in strictly increasing order.
Hint. Induct on the number of nodes. Assume both subtrees' inorder outputs are already sorted; where does fall relative to each?
Answer sketch. Induct on tree size . Base: the empty tree emits nothing
(vacuously sorted); a single node emits one key. Step: let be the root with
left subtree and right subtree , each of size . By the induction
hypothesis, inorder of is a sorted list of keys, every one
(the BST property applies to all of , not just 's child), and inorder of
is sorted with every key . The inorder traversal
concatenates: .
The first block is the last block, and each block is
internally sorted, so the whole sequence is strictly increasing.
(This is why the lab checks correctness by asserting inorder() equals the sorted
key list after arbitrary insertion orders.)
4. ▶ Random-BST average search cost (rating 26 · cf. 6.2.2-9)
Problem. Build a BST by inserting distinct keys in a uniformly random order (all orders equally likely). Show that the average number of comparisons in a successful search is
and explain why the same constant governs quicksort.
Hint. Let be the expected internal path length (sum of node depths). The first inserted key is the root; it splits the other keys into subtrees of sizes and with uniform on , and every node below the root is one comparison deeper. Set up the recurrence for and note it is identical to quicksort's comparison recurrence.
Answer sketch. With the root splitting the remaining keys, and nodes each one level deeper,
This is exactly quicksort's recurrence (Module 06), because building a random BST performs the same comparisons quicksort does, the root playing the pivot. Solving (multiply by , subtract the instance, telescope) gives , and since the average search visits path length plus one node, . (Verified against the closed form: , , with and agreeing exactly.) As and ,
— only about 39% above the perfectly balanced , with no balancing logic. The shared is the quicksort ↔ BST correspondence.
5. Hibbard deletion is not randomness-preserving (rating 30 · cf. 6.2.2-15)
Problem. Hibbard deletion removes a two-child node by replacing it with its symmetric successor (the minimum of its right subtree). Show that repeatedly deleting and re-inserting keys does not preserve the "random BST" distribution — so the clean average of Problem 4 is not maintained under updates. What is the qualitative effect on expected search cost?
Hint. The successor is always drawn from the right subtree. What asymmetry does that build in over many deletions? Compare the distribution of tree shapes a fixed number of random insertions produces against what you get after a delete/insert cycle.
Answer sketch. The random-insertion model gives a specific, non-uniform distribution over tree shapes — for keys, the balanced tree (root the median) occurs with probability and each of the four lopsided shapes with probability (verified by enumerating all insertion orders). Hibbard deletion breaks this: because the replacement is always the right subtree's minimum, deletions systematically pull structure from the right and leave the tree biased leftward, so the post-deletion shape distribution is no longer the random-insertion one. Since the result of Problem 4 depends on that exact distribution, it no longer applies after updates. Knuth's analysis (and Eppinger's later experiments, cited in §3) show the expected internal path length drifts upward under long streams of random delete/insert pairs — toward rather than staying at — the asymmetry accumulating over many operations. The practical fixes are to alternate predecessor/successor replacement (restoring symmetry) or to switch to a self-balancing tree (Problem 6), which guarantees the bound regardless of the update history.
6. ▶ AVL height bound via Fibonacci trees; tightness (rating 25 · cf. §6.2.3)
Problem. An AVL tree is height-balanced: at every node the two subtree heights differ by at most . Let be the minimum number of nodes in an AVL tree of height (edges). Derive a recurrence for , solve it in terms of Fibonacci numbers, and conclude that an -node AVL tree has height — specifically . Show the bound is tight by exhibiting the extremal trees.
Hint. To be as tall as possible with as few nodes as possible, make one subtree height and the other (the largest gap the invariant allows). That gives ; add to both sides to reveal the Fibonacci recurrence.
Answer sketch. The sparsest height- AVL tree has a root whose subtrees are sparsest AVL trees of heights and , so
Adding : , so satisfies the Fibonacci recurrence, giving (with ). (Verified: .) The extremal trees are the Fibonacci trees — recursively, height- tree = root with a height- and a height- Fibonacci subtree — and they attain , so the bound is tight. Since with , inverting gives . (Verified: bound so height ; bound so height — matching the lab's enforced ceilings.) An AVL tree is thus at most ~44% taller than a perfect tree, guaranteed.
7. Linear-probing successful-search analysis (rating 22 · cf. 6.4-8)
Problem. In an open-addressing hash table with linear probing (on collision, step to the adjacent slot), let be the load factor. Knuth's 1962 result gives the average number of probes for a successful search as
Explain the mechanism (primary clustering) that drives this formula, evaluate it and the unsuccessful-search formula at and , and say what the comparison reveals.
Hint. A successful search retraces the probe path taken when the key was inserted, so its cost is the average insertion cost so far. Occupied runs ("clusters") lengthen at both ends because any key hashing anywhere into a run must probe to the run's end — long runs beget longer runs.
Answer sketch. Primary clustering: linear probing places colliding keys into contiguous runs, and a run of length captures every key hashing to any of its slots, so runs grow super-linearly and a search's cost is dominated by how long a run it lands in. Averaging insertion costs over the fill history yields Knuth's for a hit and $C' \approx \tfrac12(1
- 1/(1-\alpha)^2)$ for a miss. Evaluating (verified):
The reveal: the unsuccessful cost blows up quadratically in — from to as the table fills from half to 90% — while the successful cost only grows linearly. That runaway miss cost is the fingerprint of clustering and the reason open-addressing tables resize well before . (The lab fills a -slot table and confirms probes at and a climb past at .)
8. ▶ Double vs. uniform hashing; secondary clustering (rating 28 · cf. §6.4)
Problem. Double hashing resolves collisions with a key-dependent step (with prime, so ). Explain why this removes the primary clustering of linear probing, why it nonetheless approximates the idealized uniform hashing model, and what "secondary clustering" means. Compare the average probes at against linear probing.
Hint. Under uniform hashing every key's probe sequence is an independent random permutation of the slots, giving successful cost and unsuccessful . Ask how close double hashing's per-key sequence comes to "independent random," and where it can still fall short (keys sharing a probe sequence).
Answer sketch. Two keys colliding at almost always get different steps , so they do not march in lockstep down the table — the runs that define primary clustering never form. Because the step sequence visits all slots, and with two independent-ish hash values each key follows an essentially distinct pseudo-random probe path, so double hashing tracks the uniform-hashing averages closely. Secondary clustering is the residual effect: keys that collide in both and (or, in weaker schemes like quadratic probing, keys sharing only ) follow the same probe sequence and thus still pile up — a milder, second-order clustering. Numerically at (verified against the uniform-hashing formulas):
versus linear probing's and (Problem 7) — a decisive win, especially on the unsuccessful search where clustering hurt most. (The lab inserts the same key set into both tables at and confirms double hashing wins.)
Your solutions
Use this space to log your own work — a restated problem, your approach, and how it compared with the sketch above.
Exercise N (rating RR)
Approach. Answer / proof. Compared with the sketch: what you did differently, what you missed.