Algorithm Search⌘K

Proofs: Bucket queue

These are the human proofs of Bucket queue, at full length.

The bucket queue returns an item of smallest key full

This proof shows: correctness, termination.

Let SS be the set of items in the queue, and for x∈Sx \in S let key[x]\mathit{key}[x] be its key. The queue is correct if EXTRACT-MIN returns some x∈Sx \in S with key[x]=min⁡y∈Skey[y]\mathit{key}[x] = \min_{y \in S} \mathit{key}[y], removes it, and the other operations change SS and the keys as their names say.

Invariants. Between operations:

(B) for each kk, the bucket B[k]B[k] holds exactly the items x∈Sx \in S with key[x]=k\mathit{key}[x] = k, and each item at most once;

(C) 0≤cur≤C+10 \le \mathit{cur} \le C + 1, and B[k]B[k] is empty for each k<curk < \mathit{cur}.

Initially SS is empty, every bucket is empty, and cur=C+1\mathit{cur} = C + 1, so (B) and (C) hold.

INSERT(x,k)(x, k) with 0≤k≤C0 \le k \le C and x∉Sx \notin S. Line L2 adds xx to SS with key kk and appends it to B[k]B[k] only, so (B) holds. If k≥curk \ge \mathit{cur}, the only bucket that changed has index at least cur\mathit{cur}, so (C) holds. Else line L3 sets cur=k\mathit{cur} = k; the buckets below kk were below the old cursor and are empty, so (C) holds.

DELETE(x)(x) with x∈Sx \in S. By (B), xx is in B[key[x]]B[\mathit{key}[x]] and nowhere else. Line L4 removes it from that bucket and from SS, so (B) holds. A bucket only lost an item, so (C) holds.

DECREASE-KEY(x,k)(x, k) with k≤key[x]k \le \mathit{key}[x] is a DELETE followed by an INSERT of the same item with key kk, so both invariants hold, and afterwards key[x]=k\mathit{key}[x] = k.

EXTRACT-MIN. Let SS be non-empty, and let μ=min⁡y∈Skey[y]\mu = \min_{y \in S} \mathit{key}[y]. By (B), B[μ]B[\mu] is non-empty, and by (C), μ≥cur\mu \ge \mathit{cur}, so cur≤μ≤C\mathit{cur} \le \mu \le C.

The loop of line L8. Claim: before each test, cur≤μ\mathit{cur} \le \mu and B[k]B[k] is empty for each k<curk < \mathit{cur}. It holds before the first test, as shown. If the test is true, B[cur]B[\mathit{cur}] is empty, so cur≠μ\mathit{cur} \ne \mu and cur<μ\mathit{cur} < \mu; after the increment, cur≤μ\mathit{cur} \le \mu and B[k]B[k] is empty for each kk below the new cursor. Each iteration raises cur\mathit{cur} by one and cur≤μ\mathit{cur} \le \mu stays true, so the loop stops after at most μ−cur\mu - \mathit{cur} iterations, and it never reads a bucket beyond CC.

When it stops, B[cur]B[\mathit{cur}] is non-empty, so by (B) some item has key cur\mathit{cur}, hence μ≤cur\mu \le \mathit{cur}, and with the claim, cur=μ\mathit{cur} = \mu. Line L9 takes an item xx of B[μ]B[\mu], so key[x]=μ\mathit{key}[x] = \mu, and line L10 deletes it. Line L11 returns (x,μ)(x, \mu). The loop kept (C), and DELETE keeps (B) and (C).

FIND-MIN is the same without line L10, and it changes only the cursor, which keeps (C).

Theorem. Each sequence of operations on a bucket queue with keys in 0…C0 \ldots C stops, and each EXTRACT-MIN or FIND-MIN on a non-empty queue returns an item of smallest key and that key. Items with equal keys come out in the order in which they last entered their bucket.

Proof. Each operation other than EXTRACT-MIN and FIND-MIN is straight-line code, and their loop stops, as shown. The first claim is the analysis of EXTRACT-MIN above. For the last, each bucket is a first-in, first-out list, and line L9 takes its first item. ■\blacksquare

Back to Bucket queue