Algorithm Search⌘K

Proofs: Spreadsort

These are the human proofs of Spreadsort, at full length.

Spreadsort sorts its input and terminates full

This proof shows: correctness, termination.

Let ff be the key map, with x<y⇔f(x)<f(y)x < y \Leftrightarrow f(x) < f(y). Write g(x)=f(x)g(x) = f(x) for short. For a task (lo,hi)(lo, hi) with mnmn and mxmx the least and the greatest value of gg on the range, write rr for the number of bits of mx−mnmx - mn.

Fact 1. In a pass with shift ss, the bin β(x)=(g(x)−mn)≫s\beta(x) = (g(x) - mn) \gg s does not decrease when g(x)g(x) grows. So if β(x)<β(y)\beta(x) < \beta(y) then x<yx < y.

Proof. ⌊t/2s⌋\lfloor t / 2^s \rfloor does not decrease in tt. If β(x)<β(y)\beta(x) < \beta(y), then g(x)−mn<g(y)−mng(x) - mn < g(y) - mn, since otherwise β(x)≥β(y)\beta(x) \ge \beta(y). So g(x)<g(y)g(x) < g(y) and x<yx < y. □\square

Fact 2. Each bin of the pass has a spread less than 2s2^s. If s=0s = 0, all keys of a bin are equal.

Proof. Keys of bin jj have j2s≤g(x)−mn<(j+1)2sj 2^s \le g(x) - mn < (j + 1) 2^s, so two of them differ by less than 2s2^s. For s=0s = 0 the difference is 0, so gg and therefore the keys are equal. □\square

Fact 3. The bins are in range: β(x)<2b\beta(x) < 2^b for each key.

Proof. g(x)−mn≤mx−mn<2r=2b+sg(x) - mn \le mx - mn < 2^r = 2^{b + s}, so β(x)<2b\beta(x) < 2^b. □\square

Invariant. (I1) The tasks on the stack have disjoint ranges. (I2) AA holds the input multiset. (I3) For indices i<ji < j that are not in the same task, A[i]≤A[j]A[i] \le A[j].

Initialization. The stack has the one task (0,n)(0, n), and each pair of indices is in it, so (I1) to (I3) hold.

Maintenance. Pop the task (lo,hi)(lo, hi). The pairs with one index outside [lo,hi)[lo, hi) keep their relation, because the range keeps its multiset of keys.

  • If m<Mm < M, insertion sort puts the range in order, so the pairs inside the range now satisfy (I3).
  • If mn=mxmn = mx, all keys of the range are equal, and (I3) holds inside it.
  • Otherwise, line L10 counts the bins, which are valid by Fact 3, and line L11 permutes the range so that bin jj fills start[j]…start[j+1]−1start[j] \ldots start[j+1] - 1. The permutation only swaps keys, so (I2) holds. Take i<ji < j inside the range in different bins. The bin of A[i]A[i] is lower, so A[i]<A[j]A[i] < A[j] by Fact 1. If s=0s = 0, keys in the same bin are equal by Fact 2, so (I3) holds for the whole range. If s>0s > 0, line L13 pushes each bin with two or more keys as a task. Its range is inside [lo,hi)[lo, hi), so (I1) holds, and pairs in the same bin are in the same new task, so (I3) is not claimed for them. A bin with one key has no pair inside it.

Termination. For a task, let ρ\rho be the number of bits of its spread mx−mnmx - mn, which is at most KK. A task pushed by line L13 comes from a pass with s=r−b≤r−1s = r - b \le r - 1, since b≥1b \ge 1. Its spread is less than 2s2^s by Fact 2, so its ρ≤s≤r−1\rho \le s \le r - 1. So along each chain of tasks, ρ\rho drops by at least one with each pass, and a chain has at most K+1K + 1 passes. Each pass pushes at most mm tasks, with disjoint ranges of at least two keys. So the tasks at each depth have disjoint ranges, there are at most n/2n/2 of them, and the total number of pops is at most 1+(K+1)n/21 + (K + 1) n / 2. The loop ends.

Result. When the stack is empty, (I3) holds for all pairs of indices, and (I2) says that AA holds the input. So AA is the input in non-decreasing order. ■\blacksquare

Back to Spreadsort