Proofs: Cuckoo hashing
These are the human proofs of Cuckoo hashing, at full length.
Cuckoo hashing keeps its invariant and implements a dictionary full
This proof shows: correctness, termination.
We write for the set of pairs in the cells of and . The invariant is (C1) each pair is in or ; (C2) no key occurs in two cells; (C3) ; (C4) .
Theorem. Start from empty tables with and and apply any sequence of CUCKOO-INSERT, CUCKOO-SEARCH and CUCKOO-DELETE. Each operation that ends leaves (C1) to (C4) true, and equal to the map that the same sequence gives on an abstract dictionary. Each search returns the value of its key in that map, or NIL. If the hash functions of line L16 are drawn independently from a distribution under which a fixed set of at most keys can be placed with probability at least , then each insert ends with probability 1.
Proof. Empty tables satisfy (C1) to (C4) with , and they hold the empty map.
Step 1 (the two cells are enough). Assume (C1). A pair with key is in or . So a test of these two cells finds every pair with key , and if both tests fail, is not a key.
Step 2 (search). By Step 1 and (C2), lines L1 and L2 return the value of the only pair with key , if there is one, and line L3 returns NIL otherwise. Search changes nothing.
Step 3 (delete). By Step 1 and (C2), lines L13 and L14 clear the only cell with key , if there is one, and lower by 1. The other pairs do not move, so (C1) and (C2) hold, (C3) holds, and (C4) holds because decreased. The map loses exactly .
Step 4 (the eviction walk). Consider lines L6 to L11 started with a pair whose key is not a key of , on tables that satisfy (C1) and (C2). Let . We claim that before each of lines L8 and L10:
(W) is a pair of , and . Each pair of is in one of its two cells, and the keys of are distinct.
At line L6, and , so (W) holds. Line L8 swaps with the content of . After the swap, the old is in its own first cell, and the new is . If is NIL, then , each pair is in one of its cells, and line L9 adds 1 to . If is a pair, it was in , it is now out of the tables, and , so (W) holds again before line L10. Line L10 is the same with and . The keys of do not change in a swap, so they stay distinct. Hence if the walk returns at line L9 or L11, then , (C1) and (C2) hold, and has grown by 1. If it does not return after MaxLoop rounds, then by (W) the tables hold , each pair in one of its cells.
Step 5 (rehash). Line L15 sets . Line L16 empties the tables and sets . Line L17 runs the walk for each pair of in turn. The keys of are distinct, so each walk starts with a key that is not yet in the tables, and Step 4 applies. If all walks return, then , with (C1) and (C2), and by (C3). If one walk fails, line L17 goes back to line L16 and starts again from the same . So when REHASH returns, and (C1) to (C3) hold.
Step 6 (insert). If line L4 finds key , it replaces the value in place. No pair moves and the map is the old map with mapped to . Else is not a key, by Step 1. Line L5 keeps by Step 5, and after it : either the test failed, or was doubled from a value . If , then . If , then , because and . By Step 4 with , either the walk places all of , or it leaves one pair outside with . In the second case, line L12 calls REHASH with , and by Step 5 the result is . In both cases and , so (C1) to (C4) hold and the map is the old map plus .
Step 7 (termination). Each walk has at most MaxLoop rounds, so it ends. REHASH repeats line L16 until one draw of places all of . The set has at most keys by (C4), so each draw succeeds with probability at least , independently of the earlier draws. The probability that the first draws all fail is at most , which tends to 0. So REHASH ends with probability 1, after an expected number of at most draws.
By induction on the number of operations, using Steps 2, 3 and 6, the theorem holds.