Algorithm Search⌘K

Proofs: Lomuto partition scheme

These are the human proofs of Lomuto partition scheme, at full length.

The Lomuto partition puts the pivot at its place and keeps the items full

This proof shows: correctness.

Claim. Let hi−lo=m≥1hi - lo = m \ge 1, let SS be the multiset of the items of A[lo…hi−1]A[lo \ldots hi-1] at the start, and let xx be the old A[hi−1]A[hi - 1]. Then LOMUTO-PARTITION(A,lo,hi)(A, lo, hi) stops after m−1m - 1 steps of its loop and returns an index pp with lo≤p≤hi−1lo \le p \le hi - 1. After the call, A[lo…hi−1]A[lo \ldots hi-1] holds SS, A[p]=xA[p] = x, each item of A[lo…p−1]A[lo \ldots p-1] is at most xx, and each item of A[p+1…hi−1]A[p+1 \ldots hi-1] is larger than xx. No item outside the range changes.

Proof. Lines L1 and L2 set x=A[hi−1]x = A[hi - 1] and i=loi = lo. We prove this invariant of the loop of line L3, before the step for jj, for j=lo,lo+1,…,hi−1j = lo, lo + 1, \ldots, hi - 1:

(L) lo≤i≤jlo \le i \le j. Each item of A[lo…i−1]A[lo \ldots i-1] is at most xx. Each item of A[i…j−1]A[i \ldots j-1] is larger than xx. A[hi−1]=xA[hi-1] = x. The range holds SS, and nothing outside it has changed.

  1. Start. For j=loj = lo, we have i=j=loi = j = lo, so both parts are empty. No line has changed the array.
  2. A large item. Assume (L) for j≤hi−2j \le hi - 2 and A[j]>xA[j] > x. The test of line L4 fails, and nothing changes. Now A[i…j]A[i \ldots j] holds only items larger than xx, so (L) holds for j+1j + 1.
  3. A small item. Assume (L) for j≤hi−2j \le hi - 2 and A[j]≤xA[j] \le x. If i=ji = j, line L5 swaps A[j]A[j] with itself, and after line L6 the left part A[lo…j]A[lo \ldots j] holds only items at most xx, while the large part A[j+1…j]A[j + 1 \ldots j] is empty. If i<ji < j, then A[i]A[i] is in the large part, so A[i]>xA[i] > x. Line L5 swaps A[i]A[i] and A[j]A[j], so now A[i]≤xA[i] \le x and A[j]>xA[j] > x. After line L6, the left part is A[lo…i]A[lo \ldots i] with the old ii, all at most xx, and the large part is A[i+1…j]A[i + 1 \ldots j], all larger than xx. In both cases (L) holds for j+1j + 1. The swap uses indices i≤j≤hi−2i \le j \le hi - 2, so it does not touch A[hi−1]A[hi - 1] or any index outside the range.
  4. End. The loop of line L3 runs for j=lo,…,hi−2j = lo, \ldots, hi - 2, so it stops after exactly m−1m - 1 steps, with (L) for j=hi−1j = hi - 1. So A[lo…i−1]≤xA[lo \ldots i-1] \le x, A[i…hi−2]>xA[i \ldots hi-2] > x and A[hi−1]=xA[hi - 1] = x, with lo≤i≤hi−1lo \le i \le hi - 1.
  5. The last swap. Line L7 swaps A[i]A[i] and A[hi−1]A[hi - 1]. If i=hi−1i = hi - 1, nothing changes. If i<hi−1i < hi - 1, the old A[i]A[i] is larger than xx and goes to index hi−1hi - 1, which is in A[i+1…hi−1]A[i+1 \ldots hi-1]. In both cases, after the swap A[i]=xA[i] = x, A[lo…i−1]≤xA[lo \ldots i-1] \le x and A[i+1…hi−1]>xA[i+1 \ldots hi-1] > x.

Line L8 returns p=ip = i. Each change was a swap of two indices in the range, so the range still holds SS and nothing outside it changed. ■\blacksquare

Rank of the pivot. The claim gives exactly p−lop - lo items at most xx other than xx itself. So when the items are distinct, xx has rank p−lo+1p - lo + 1 in the range, and A[p]A[p] is the item that a sort of the range puts at index pp.

Back to Lomuto partition scheme