This course has built eight structures and proved a bound for each. Putting the useful five in one table is the whole of the method, and the table is not new information — every entry in it was proved in one of the thirteen lessons before this one.
search insert delete min predecessor range ordered walk
sorted array log n n n 1 log n log n + k n
hash table 1 exp 1 exp 1 exp n — — —
AVL tree log n log n log n log n log n log n + k n
binary heap n log n log n 1 — — —
union–find — — — — — — —
hash table: expected, under simple uniform hashing; Θ(n) worst case
binary heap: delete of a known position; finding the key first costs n
union–find: same-set tests and merges only, at log n per operation
Three entries in that table deserve saying out loud. The hash table’s three 1s are expected under an assumption about the keys, with a Θ(n) worst case that no hash function removes. The heap’s min is 1 but its search is n, because it keeps no order between siblings. And union–find’s row is dashes all the way across, because it is not a container at all: it answers “are these two together” and holds no retrievable keys.
The refusals, which are where most choices are actually made
A hash table cannot answer predecessor (“the largest key below k”), cannot answer a range query, and cannot produce the keys in order without sorting them from scratch. This is not slowness: hashing deliberately destroys the order, which is how it gets its constant. The dash is the right entry, and a column of numbers with a large number in that cell would be a lie.
That refusal is the in-memory form of a mistake System Design counts in I/O. “Hash vs Tree for Ranges” prices a hash index and a B-tree on a workload of nine hundred point lookups and a hundred small ranges a second, and the hash index — which wins the point lookup one I/O to three — loses the mix by a factor of nearly a hundred and seventy, because its only way to answer a range is to read the whole table. Same mistake, with a disk attached and a number on it.
One mix, executed
The lab costs a mix by running it. It ranks the five sequence representations whose cost model it can execute — dynamic array, sorted array, doubly-linked list, stack and queue — rather than the five in the table above, because those are the five with a per-operation cost model already proved on this course. The lesson it teaches is the same one, and it is about the refusals:
n = 32, mostly lookups: 12 search, 2 index, 2 delete, 2 min
sorted array 108 cheapest; binary search
dynamic array 478 scans
doubly-linked list 513 scans, and pays to reach a position
stack — cannot search, index, delete or take a min
queue — the same four refusals
n = 32, insert at one end, remove at the other: 8 + 8
doubly-linked list 168 cheapest
dynamic array 440 shifts on every front insertion
sorted array — cannot be told where to insert
stack, queue — cannot delete at a position
Two mixes, and the winner changed and the refusals changed with it. The sorted array is four to five times cheaper than anything else on the lookup-heavy mix and cannot run the second one at all — not slowly, at all — because an insertion at a caller-chosen position is not an operation a sorted array has. That is the shape of a real structure choice far more often than a factor of two on a shared operation.
And the ranking is a measurement of one mix at one size. 108 against 513 is a fact about eighteen operations on thirty-two elements. Move the proportions and the order changes; move n and the gaps change, because log n and n diverge. The table of bounds is what generalises, the measured ranking is what convinces, and the honest report uses both — the bound to say what will happen and the count to show it happening.