Algorithm Search⌘K

Proofs: Quadratic probing

These are the human proofs of Quadratic probing, at full length.

Quadratic probing with triangular offsets finds each key and each free slot full

This proof shows: correctness, termination.

Let m=2pm = 2^p with p≥0p \ge 0. For a key kk and i≥0i \ge 0, write pi(k)=(h(k)+i(i+1)/2) mod mp_i(k) = (h(k) + i(i+1)/2) \bmod m. A slot is full when it holds a key, and free when it is EMPTY or DELETED.

Lemma 1 (coverage). The values i(i+1)/2 mod mi(i+1)/2 \bmod m for i=0,1,…,m−1i = 0, 1, \ldots, m-1 are pairwise different. So for each key kk, the slots p0(k),…,pm−1(k)p_0(k), \ldots, p_{m-1}(k) are the mm slots of the table, each one exactly once.

Proof. For m=1m = 1 there is one value. Let m≥2m \ge 2 and assume that 0≤i<j≤m−10 \le i < j \le m-1 and i(i+1)/2≡j(j+1)/2(mod2p)i(i+1)/2 \equiv j(j+1)/2 \pmod{2^p}. Then 2p2^p divides j(j+1)−i(i+1)2=(j−i)(j+i+1)2\frac{j(j+1) - i(i+1)}{2} = \frac{(j-i)(j+i+1)}{2}, so 2p+12^{p+1} divides (j−i)(j+i+1)(j-i)(j+i+1). The sum of the two factors is 2j+12j + 1, which is odd, so one factor is odd. An odd factor has no factor 2, so 2p+12^{p+1} divides the other factor. But 0<j−i≤m−1<2p+10 < j - i \le m - 1 < 2^{p+1} and 0<j+i+1≤(m−1)+(m−2)+1=2p+1−2<2p+10 < j + i + 1 \le (m-1) + (m-2) + 1 = 2^{p+1} - 2 < 2^{p+1}. A positive integer less than 2p+12^{p+1} is not a multiple of 2p+12^{p+1}. This is a contradiction. So the mm values are different, and as they lie in {0,…,m−1}\{0, \ldots, m-1\}, they are all of its values. Adding h(k)h(k) modulo mm is a bijection of {0,…,m−1}\{0, \ldots, m-1\}, which gives the second claim. □\square

Lemma 2 (the variable jj). In QP-SEARCH and QP-INSERT, at the start of the iteration with counter ii, j=pi(k)j = p_i(k).

Proof. By induction on ii. For i=0i = 0, line L1 or L7 sets j=h(k)=p0(k)j = h(k) = p_0(k). If j=pi(k)j = p_i(k) at the start of iteration ii and the iteration does not return, line L5 or L10 sets jj to (pi(k)+i+1) mod m=(h(k)+i(i+1)/2+i+1) mod m=(h(k)+(i+1)(i+2)/2) mod m=pi+1(k)(p_i(k) + i + 1) \bmod m = (h(k) + i(i+1)/2 + i + 1) \bmod m = (h(k) + (i+1)(i+2)/2) \bmod m = p_{i+1}(k). □\square

The invariant. Consider a table built from an EMPTY table by calls of QP-INSERT (each with its precondition) and QP-DELETE.

(Q) No key occurs in two slots. For each key kk in the table there is a tt with 0≤t≤m−10 \le t \le m-1 such that T[pt(k)]=kT[p_t(k)] = k and none of the slots p0(k),…,pt−1(k)p_0(k), \ldots, p_{t-1}(k) is EMPTY.

Lemma 3. QP-SEARCH(T,k)(T, k) returns the slot of kk if kk is in TT, and NIL otherwise, when (Q) holds. It does not change TT.

Proof. QP-SEARCH writes nothing. It returns a slot jj only at line L4, where T[j]=kT[j] = k, so a returned slot holds kk. If kk is not in TT, no slot passes the test of line L4, so the result is NIL (line L3 or L6).

Let kk be in TT, with tt as in (Q). By Lemma 2, iteration ii looks at pi(k)p_i(k). For i<ti < t, the slot pi(k)p_i(k) is not EMPTY by (Q), so line L3 does not return. It does not hold kk: by Lemma 1, pi(k)≠pt(k)p_i(k) \ne p_t(k), and by (Q) kk is only at pt(k)p_t(k). So line L4 does not return either. In iteration t≤m−1t \le m-1 the slot pt(k)p_t(k) holds kk, which is not EMPTY, and line L4 returns it. □\square

Lemma 4. If kk is not in TT and (Q) holds, QP-INSERT(T,k)(T, k) either raises "the table is full", and then every slot is full and TT is not changed, or it writes kk into one free slot, and then (Q) holds again.

Proof. By Lemma 2, iteration ii tests slot pi(k)p_i(k), and by Lemma 1 the mm iterations test every slot once. If no slot is free, line L9 never writes and line L11 raises the error. Otherwise let tt be the first iteration at which pt(k)p_t(k) is free. Line L9 writes kk there. The slots p0(k),…,pt−1(k)p_0(k), \ldots, p_{t-1}(k) were full at line L9, and they stay full, so none of them is EMPTY: (Q) holds for kk. As kk was not in TT, it now occurs once. For another key k′k', its slot is not changed, because line L9 writes only to a free slot. The write turns one free slot into a full one, so the set of EMPTY slots does not grow, and (Q) stays true for k′k'. □\square

Lemma 5. If (Q) holds, QP-DELETE(T,k)(T, k) removes kk when it is present, changes nothing else, and (Q) holds after it.

Proof. By Lemma 3, line L12 finds the only slot that holds kk, or NIL. If NIL, nothing changes. Otherwise line L13 writes DELETED there, so kk is no longer in TT. The set of EMPTY slots does not change, and no other key moves, so (Q) holds for each other key. □\square

Theorem. Start from a table of EMPTY slots, and apply any sequence of QP-INSERT calls (each for a key that is not in the table) and QP-DELETE calls. After each call, the set of keys in TT is the set given by the sequence of operations, each QP-SEARCH answers correctly, and each QP-INSERT succeeds unless all mm slots are full. Each call ends after at most mm iterations of its loop.

Proof. The EMPTY table has no keys, so (Q) holds. By induction on the number of calls, with Lemmas 4 and 5 for the step, (Q) holds after each call, and each call changes the set of keys as its specification says. Lemma 3 then gives the answer of each search. The loops of lines L2 and L8 have exactly mm iterations at most, because the counter ii grows by 1 from 0 to m−1m-1, and QP-DELETE makes one search and one write. ■\blacksquare

Back to Quadratic probing