Algorithm Search⌘K

Proofs: Double hashing

These are the human proofs of Double hashing, at full length.

Expected probes of open addressing under uniform hashing full

This proof shows: time.expected, time.worst.

Worst case. Each loop of the page runs at most mm times, by the proof of correctness, so each operation makes at most mm probes. For the lower bound, take n≤mn \le m keys k1,…,knk_1, \ldots, k_n with the same h1h_1 and the same h2h_2; for h1(k)=k mod mh_1(k) = k \bmod m and h2(k)=1+(k mod (m−2))h_2(k) = 1 + (k \bmod (m-2)) the keys kj=j⋅m(m−2)k_j = j \cdot m(m-2) work. They have the same probe sequence, so the insert of kjk_j probes jj slots, and the last insert and each later search for knk_n probe nn slots. With n=mn = m this is Θ(m)\Theta(m).

Model for the expected case. The uniform hashing assumption says that the probe sequence of each key is a uniformly random permutation of the mm slots, independent of the other keys. Assume a table with no DELETED slot that holds n<mn < m keys, so α=n/m<1\alpha = n/m < 1, and that the keys were inserted without knowledge of the random sequences.

Claim 1. A search for a key that is not in the table makes at most 1/(1−α)1/(1 - \alpha) probes in expectation.

Proof. Let XX be the number of probes. The search goes on after probe ii only if the first ii probed slots are all occupied. The probe sequence of the absent key is a uniform random permutation, independent of which nn slots are occupied. So for i≥1i \ge 1,

Pr⁡[X>i]=nm⋅n−1m−1⋯n−i+1m−i+1≤(nm)i=αi,\Pr[X > i] = \frac{n}{m} \cdot \frac{n - 1}{m - 1} \cdots \frac{n - i + 1}{m - i + 1} \le \Big(\frac{n}{m}\Big)^{i} = \alpha^{i},

because (n−j)/(m−j)≤n/m(n - j)/(m - j) \le n/m for 0≤j<n≤m0 \le j < n \le m. Hence E[X]=∑i≥0Pr⁡[X>i]≤∑i≥0αi=1/(1−α)E[X] = \sum_{i \ge 0} \Pr[X > i] \le \sum_{i \ge 0} \alpha^i = 1/(1 - \alpha). □\square

An insert of a new key makes the same probes as a search that fails, so it also makes at most 1/(1−α)1/(1 - \alpha) probes in expectation.

Claim 2. With no deletions, a search for a key chosen uniformly from the nn keys of the table makes at most 1αln⁡11−α\frac{1}{\alpha} \ln \frac{1}{1 - \alpha} probes in expectation.

Proof. A search for a key follows the same probes as its insert. With no deletions, the key inserted as the (j+1)(j + 1)-st, for 0≤j<n0 \le j < n, was inserted into a table with jj keys, so by Claim 1 its search makes at most 1/(1−j/m)=m/(m−j)1/(1 - j/m) = m/(m - j) probes in expectation. Average over the nn keys:

1n∑j=0n−1mm−j=mn∑t=m−n+1m1t≤1α∫m−nmdxx=1αln⁡mm−n=1αln⁡11−α.\frac{1}{n} \sum_{j=0}^{n-1} \frac{m}{m - j} = \frac{m}{n} \sum_{t = m - n + 1}^{m} \frac{1}{t} \le \frac{1}{\alpha} \int_{m - n}^{m} \frac{dx}{x} = \frac{1}{\alpha} \ln \frac{m}{m - n} = \frac{1}{\alpha} \ln \frac{1}{1 - \alpha}.

The inequality holds because 1/t≤∫t−1tdx/x1/t \le \int_{t-1}^{t} dx/x for each t≥1t \ge 1, as 1/x≥1/t1/x \ge 1/t on [t−1,t][t - 1, t]. ■\blacksquare

How far double hashing is from the model. Double hashing does not give a uniform random permutation: there are at most m(m−1)m(m-1) sequences, one per pair (h1(k),h2(k))(h_1(k), h_2(k)). The two claims are therefore exact only for the model. Guibas and Szemerédi (1978) and Lueker and Molodowitch (1993) proved that, with h1h_1 and h2h_2 ideal random functions, the expected number of probes of double hashing equals the uniform hashing value plus a term that tends to 0 as mm grows, for fixed α\alpha (below about 0.319 in the first paper, and for each α<1\alpha < 1 in the second). Their proofs are long and are not repeated here.

Double hashing keeps its probe invariant and implements a dictionary full

This proof shows: correctness, termination.

Write pk(i)=(h1(k)+i⋅h2(k)) mod mp_k(i) = (h_1(k) + i \cdot h_2(k)) \bmod m, and assume gcd⁡(h2(k),m)=1\gcd(h_2(k), m) = 1 for each key kk. A slot is free when it is EMPTY or DELETED, and occupied when it holds a pair. The map of the table is the set DD of the pairs in occupied slots.

Lemma 1 (the probe sequence is a permutation). For each key kk, the values pk(0),…,pk(m−1)p_k(0), \ldots, p_k(m-1) are the mm slots, each exactly once.

Proof. Suppose pk(i)=pk(i′)p_k(i) = p_k(i') with 0≤i<i′≤m−10 \le i < i' \le m - 1. Then mm divides (i′−i)h2(k)(i' - i) h_2(k). Since gcd⁡(h2(k),m)=1\gcd(h_2(k), m) = 1, mm divides i′−ii' - i. But 0<i′−i<m0 < i' - i < m, a contradiction. So the mm values are distinct, and they are mm values in {0,…,m−1}\{0, \ldots, m-1\}, so they are all the slots. □\square

Invariant.

  • (D1) If key kk is in slot pk(t)p_k(t), then none of pk(0),…,pk(t−1)p_k(0), \ldots, p_k(t-1) is EMPTY.
  • (D2) No key is in two occupied slots.

Lemma 2 (complete scan). Assume (D1) and (D2). Follow pk(0),pk(1),…p_k(0), p_k(1), \ldots and stop at the first EMPTY slot, or after mm probes. If kk is in the table, the scan meets its slot. If the scan does not meet kk, then kk is not in the table.

Proof. If kk is in slot pk(t)p_k(t), then t≤m−1t \le m - 1 by Lemma 1, and by (D1) no slot before position tt is EMPTY, so the scan reaches position tt. The second sentence is the contrapositive of the first. □\square

Theorem. Start from a table with all slots EMPTY, and apply any sequence of DH-INSERT, DH-SEARCH and DH-DELETE. Each call ends after at most mm passes of its loop. After each call (D1) and (D2) hold, DD is the map that the same sequence gives on an abstract dictionary (except that an insert into a table with no free slot and without kk reports a full table and changes nothing), and each search returns the value of its key in DD, or NIL.

Proof. Termination. Each loop runs with i=0,1,…,m−1i = 0, 1, \ldots, m - 1, and ii grows by 1 at each pass, so it stops after at most mm passes.

Base. In the empty table no slot is occupied, so (D1) and (D2) hold, and DD is empty.

Search. The loop of lines L13 to L17 is the scan of Lemma 2. Line L16 returns the value of the occupied slot with key kk, which is the only one by (D2). If the scan ends at EMPTY or after mm probes, kk is absent by Lemma 2 and NIL is right. No slot changes.

Delete. Lines L18 to L21 are the same scan. If they find kk in slot qq, line L21 makes qq DELETED, so DD loses exactly the pair of kk. No slot becomes EMPTY, so for each other key the slots before it on its path are still not EMPTY, and (D1) holds. (D2) holds since a pair was only removed. If the scan does not find kk, then kk is absent and nothing changes.

Insert. The loop of lines L2 to L10 follows pk(0),pk(1),…p_k(0), p_k(1), \ldots and stops at the first EMPTY slot or after mm probes, so it is the scan of Lemma 2, with a key test on each occupied slot at line L9. If it finds kk, line L10 changes only the value, so (D1), (D2) and the slots are as before, and DD maps kk to vv.

Else kk is absent, by Lemma 2. During the scan, jj is set at lines L5 or L8 to the first free slot of the path, if the scan meets one. Let j=pk(t)j = p_k(t). All the slots pk(0),…,pk(t−1)p_k(0), \ldots, p_k(t-1) were met before jj and were not free, so they are occupied, and in particular not EMPTY. If jj is NIL, the scan met no free slot. If it stopped at an EMPTY slot, that slot would have set jj; so it made mm probes, all occupied, and by Lemma 1 every slot is occupied by a key other than kk. Then line L11 reports a full table and changes nothing, as stated.

Otherwise line L12 puts (k,v)(k, v) in slot pk(t)p_k(t). Then (D1) holds for kk, by the fact above. For each other key, line L12 turned a free slot into an occupied one, and no slot became EMPTY, so (D1) still holds for it. (D2) holds because kk was absent. DD gains exactly the pair (k,v)(k, v).

By induction on the number of calls, the claims hold after each call. ■\blacksquare

Back to Double hashing