← The Museum of Algorithms
3.3

Wing III · The Architecture of Order

The Birthday
Paradox

Hashing — finding without searching

VOLUME III — Sorting and Searching SECTION 6.4 1953 Amdahl · Luhn

Gather twenty-three strangers in a room and it is more likely than not that two of them share a birthday. Almost no one believes this the first time they hear it — twenty-three against three hundred and sixty-five feels absurdly lopsided — and the disbelief is the point. We instinctively compare each person to ourselves, but the collision can happen between any pair, and twenty-three people make two hundred and fifty-three pairs. Coincidence scales with pairs, not with people, and pairs grow as the square. This is the birthday paradox, and it is the single most important fact about hash tables — because a hash table is a room, its buckets are the days of the year, and the keys are the strangers walking in.

A hash table performs a small miracle: it finds an item without searching for it. Instead of comparing your key against the stored ones — the whole enterprise of the trees in the last two rooms — it computes an address directly from the key and goes straight there. A function h(key) grinds the key into a bucket number, and that bucket is where the item lives. No traversal, no comparisons, no depth: on average, a single step. It is the fastest lookup we know, and databases, compilers, caches, and the dictionary in every programming language are built on it.

"A hash table trades order for speed. It cannot tell you the smallest key or list them in sequence — it scattered them on purpose. What it gives back for that sacrifice is the answer to 'is X here, and where?' in one step." — after D. E. Knuth, TAOCP Vol. 3, §6.4

I · The Inevitable CollisionWhen two keys want one bucket

The miracle has a catch, and the birthday paradox is its name. Because the hash function scatters many possible keys across few buckets, two different keys will eventually compute the same address — a collision — and, exactly as with birthdays, collisions arrive far sooner than intuition expects. In a table of m buckets, the first collision is likely once you have inserted only about 1.18·√m keys — a mere handful for a small table. You cannot hash your way out of this; the pigeonhole principle guarantees it. So the real design question is never "how do I avoid collisions?" but "what do I do when they happen?" There are two classic answers, and the instrument below runs them side by side on the very same keys.

Type a word — or let it deal you random ones — and watch our honest little hash function, h = (h·31 + letter) mod m, chew the letters into a bucket number in full view. Then watch the key drop into two tables at once. On the left, linear probing: if the bucket is taken, walk forward to the next free slot. On the right, separate chaining: hang the key on a little list dangling from the bucket. Keep going, and feel the birthday paradox arrive.

Instrument 3.3
The Name Collider
HASH TABLE · linear probing vs chaining · visible h(key)
Two tables, one key stream — probing (left) vs chaining (right)empty
Type a word and press Insert to see h(key) computed letter by letter.
The birthday oddsready
P(at least one collision)
0%
With m=23 buckets, a collision becomes likely after ~6 keys (≈1.18·√m).
Keys
0
Load α
0.00
1st collision
—

Both tables receive identical keys and compute the identical bucket h(key); they differ only in what they do when that bucket is already taken. Linear probing keeps the data compact and cache-friendly but forms clusters that lengthen every future search; chaining stays fast under load but pays in scattered list nodes — and, unlike probing, can never fill up.

II · Load, Clusters & the Cost of FullnessWhat collisions cost

The health of a hash table is measured by one number: the load factor α = n/m, the fraction of buckets in use. As long as α stays modest, both methods answer in nearly constant time. But their fates diverge as the table fills. Separate chaining degrades gracefully — the average chain has length α, so even a table loaded beyond capacity just grows slightly longer lists. Linear probing degrades viciously: Knuth's celebrated analysis in §6.4 shows the average number of probes for an unsuccessful search grows like ½(1 + 1/(1−α)²) — which is fine at α = 0.5 but explodes toward infinity as α → 1. And because open addressing stores everything in the table, it has a hard ceiling: at α = 1 it is full and can take no more, while a chained table shrugs and keeps going.

Linear probing's flaw is that clusters breed clusters: a full run of slots catches every key that hashes anywhere into it, so it grows, so it catches more. Knuth was the first to prove exactly how bad this "primary clustering" gets.

Fill the simulator past a load of one-half and watch the left table congeal into long amber runs while the right table's chains stay stubbily short. This is the engineer's real choice. Open addressing wins where memory and cache locality are precious and the load can be kept low (it is how the fastest in-memory tables are built, with cleverer probe sequences than the naïve linear step). Chaining wins where the load is unpredictable or high, and where deletions — awkward under probing, since a hole can break a probe chain — must be simple. Knuth quantifies both so you can choose with a theorem instead of a hunch.

III · Order Traded for SpeedThe other half of the bargain

Return, for a moment, to the tree in the previous room. A B-tree keeps every key in sorted order, so it can answer "what comes next?" and "everything between March and June" — range queries — as naturally as it answers "is X here?". A hash table cannot. By scattering keys deliberately across buckets it destroys their order, and with it the ability to enumerate, to find neighbours, to ask for a range. That is the bargain named in the pull-quote above: order traded for the fastest possible single lookup. The two structures are not rivals but complements, and real databases keep both — a B-tree index for range scans, a hash index for point lookups — over the very same data.

"An algorithm must be seen to be believed." — D. E. Knuth

Hashing radiates far beyond the dictionary. It deduplicates files, powers the load balancers that spread traffic across servers, underlies Bloom filters and caches, and — with cryptographic hash functions — gives every commit in Git and every block in a blockchain its content-addressed name. All of it descends from Hans Peter Luhn's 1953 memo at IBM and the theory Knuth laid down in §6.4, and all of it lives with the birthday paradox: collisions are not a bug to be eliminated but a certainty to be managed. Keep dealing keys into the room, and count how few it takes before two of them want the same day.