Algorithm Search⌘K

Proofs: Hoare partition scheme

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

Hoare partition stays in range, stops, and splits the range correctly full

This proof shows: correctness, termination.

Let lo<hilo < hi and let x=A[lo]x = A[lo] at the call. A round is one pass through lines L4 to L7. Each change of AA is an exchange of two items of A[lo…hi]A[lo \ldots hi], so the multiset of the range never changes, and no item outside the range changes. These are the three properties of CLRS, Problem 7-1.

Claim. (a) Lines L4 and L5 read only indices in [lo,hi][lo, hi]. (b) The call stops and returns jj with lo≤j<hilo \le j < hi. (c) At the return, each item of A[lo…j]A[lo \ldots j] is at most xx, and each item of A[j+1…hi]A[j+1 \ldots hi] is at least xx. So each item of A[lo…j]A[lo \ldots j] is at most each item of A[j+1…hi]A[j+1 \ldots hi].

The first round. The scan of line L4 starts at j=hij = hi and moves left. A[lo]=x≤xA[lo] = x \le x, so it stops at some j1≥loj_1 \ge lo. The scan of line L5 starts at i=loi = lo, and A[lo]=x≥xA[lo] = x \ge x (the exchange of this round has not happened yet), so it stops at once with i1=loi_1 = lo. Both scans read only indices in [lo,hi][lo, hi]. If i1≥j1i_1 \ge j_1, then j1=loj_1 = lo, and line L7 returns lolo, which is less than hihi. The items A[j1+1…hi]A[j_1+1 \ldots hi] were passed by the scan of jj, so they are greater than xx, and A[lo]=xA[lo] = x. So (c) holds. Otherwise lo=i1<j1lo = i_1 < j_1, and line L6 exchanges A[lo]A[lo] and A[j1]A[j_1]. After it, A[lo]A[lo] is the old A[j1]≤xA[j_1] \le x, and A[j1]A[j_1] is xx.

Invariant. At the start of each round after the first, with the current ii and jj:

(P) lo≤i<j≤hilo \le i < j \le hi. Each item of A[lo…i]A[lo \ldots i] is at most xx, and each item of A[j…hi]A[j \ldots hi] is at least xx.

Initialization. After the first round with an exchange, i=loi = lo and j=j1j = j_1. A[lo]≤xA[lo] \le x. The items A[j1+1…hi]A[j_1+1 \ldots hi] are greater than xx, and A[j1]=xA[j_1] = x. So (P) holds.

A round. Assume (P). The scan of line L4 starts at j−1≥ij - 1 \ge i and moves left. The item A[i]A[i] is at most xx, so the scan stops at some j′≥ij' \ge i. It passed the items A[j′+1…j−1]A[j'+1 \ldots j-1], which are greater than xx. So each item of A[j′+1…hi]A[j'+1 \ldots hi] is at least xx, and j′+1≤j≤hij' + 1 \le j \le hi. The scan of line L5 starts at i+1≤j′+1i + 1 \le j' + 1 and moves right. The item A[j′+1]A[j'+1] is at least xx, so the scan stops at some i′≤j′+1≤hii' \le j' + 1 \le hi. It passed the items A[i+1…i′−1]A[i+1 \ldots i'-1], which are less than xx. So each item of A[lo…i′−1]A[lo \ldots i'-1] is at most xx. Both scans read only indices in [lo,hi][lo, hi], which proves (a) for this round.

If i′<j′i' < j', line L6 exchanges A[i′]A[i'] and A[j′]A[j']. Before the exchange A[i′]≥xA[i'] \ge x and A[j′]≤xA[j'] \le x, so after it A[i′]≤xA[i'] \le x and A[j′]≥xA[j'] \ge x. So A[lo…i′]A[lo \ldots i'] is at most xx and A[j′…hi]A[j' \ldots hi] is at least xx, with lo≤i′<j′≤hilo \le i' < j' \le hi, and (P) holds for the next round.

If i′≥j′i' \ge j', line L7 returns j′j'. Then j′≤i′−1j' \le i' - 1 or j′=i′j' = i'. In both cases each item of A[lo…j′]A[lo \ldots j'] is at most xx: the items up to i′−1i' - 1 by the scan of ii, and A[j′]A[j'] itself because the scan of jj stopped there. Each item of A[j′+1…hi]A[j'+1 \ldots hi] is at least xx, as shown above. So (c) holds. Also j′≥i≥loj' \ge i \ge lo, and j′<j≤hij' < j \le hi, so lo≤j′<hilo \le j' < hi, which is (b) in this case.

Termination. In each round with an exchange, ii grows by at least 1 and jj drops by at least 1, so j−ij - i drops by at least 2. While (P) holds, j−i≥1j - i \ge 1. So after at most ⌈(hi−lo)/2⌉+1\lceil (hi - lo)/2 \rceil + 1 rounds, the test of line L6 fails, and the call returns. ■\blacksquare

Consequence for quicksort. Since lo≤j<hilo \le j < hi, both ranges [lo,j][lo, j] and [j+1,hi][j+1, hi] are not empty and are strictly shorter than [lo,hi][lo, hi]. By (c) and induction on the length, quicksort that sorts both ranges sorts A[lo…hi]A[lo \ldots hi].

Back to Hoare partition scheme