Algorithm Search⌘K

Proofs: Shell sort

These are the human proofs of Shell sort, at full length.

Shell sort sorts the array and keeps its items full

This proof shows: correctness.

For a gap h≥1h \ge 1, the chain of a residue rr with 0≤r<h0 \le r < h is the list of the items at the indices r,r+h,r+2h,…r, r + h, r + 2h, \ldots that are less than nn. The array is hh-sorted when each chain is sorted.

Lemma (one pass). One step of the loop of line L1, with the gap hh, permutes the items of each chain among the indices of that chain, and after it the array is hh-sorted.

Proof. Lines L3 to L8 only read and write the indices i,i−h,i−2h,…i, i - h, i - 2h, \ldots, which are all in the chain of i mod hi \bmod h. So the pass works on each chain apart from the others, and it does not move an item to another chain. For one chain, list its indices as c0<c1<⋯<ct−1c_0 < c_1 < \cdots < c_{t-1}. The step of line L2 for i=csi = c_s is the step of insertion sort for position ss of this chain: line L5 compares with A[cs−1],A[cs−2],…A[c_{s-1}], A[c_{s-2}], \ldots, line L6 shifts each larger item one place up in the chain, and line L8 writes the key into the gap that is left. We use this invariant, before the step for i=csi = c_s:

The items at c0,…,cs−1c_0, \ldots, c_{s-1} are the items that were there at the start of the pass, in sorted order.

It holds for s=1s = 1, because one item is sorted. Assume it before the step for csc_s. The loop of line L5 stops at the first index cqc_q, going down from csc_s, with q=0q = 0 or A[cq−1]≤keyA[c_{q-1}] \le key. Each of A[cq],…,A[cs−1]A[c_q], \ldots, A[c_{s-1}] is larger than keykey, and each moves one place up in the chain. Then line L8 puts keykey at cqc_q. The items at c0,…,cq−1c_0, \ldots, c_{q-1} are at most keykey and sorted, the items at cq+1,…,csc_{q+1}, \ldots, c_s are larger than keykey and sorted, so c0,…,csc_0, \ldots, c_s hold the old items plus keykey in sorted order. The steps for indices in other chains do not touch this chain. At the end of the pass, s=ts = t, so each chain is sorted. The step for each ii ends because jj falls by h≥1h \ge 1 in each turn of line L5 and the loop stops at j<hj < h. □\square

Theorem. If HH is a finite list of positive gaps whose last gap is 11, then SHELL-SORT(A,H)(A, H) stops, and after it AA holds the same items, in non-decreasing order.

Proof. Each line moves items only by the shift of line L6 and the write of line L8, and by the lemma each pass permutes the items of each chain. So the multiset of the items does not change. There are finitely many passes, and each pass has n−hn - h steps that each end, so the algorithm stops. The last pass has h=1h = 1. With h=1h = 1 there is one chain, the full array, so by the lemma the array is sorted after this pass. ■\blacksquare

The earlier passes are not needed for correctness. They only make the last pass fast, because they remove most of the inversions before it.

Back to Shell sort