Algorithm Search⌘K

Proofs: Three-way quicksort

These are the human proofs of Three-way quicksort, at full length.

Three-way quicksort sorts the array and keeps its items full

This proof shows: correctness.

We write SS for the multiset of the items of A[lo…hi−1]A[lo \ldots hi-1] at the start of a call. All changes to the array are swaps of two items of the range, so the range always holds SS, and items outside the range do not change.

Lemma (the partition). Assume hi−lo≥1hi - lo \ge 1, and let vv be the item read at line L2. When the loop of lines L4 to L9 stops, lo≤lt<gt≤hilo \le lt < gt \le hi, each item of A[lo…lt−1]A[lo \ldots lt-1] is less than vv, each item of A[lt…gt−1]A[lt \ldots gt-1] is equal to vv, and each item of A[gt…hi−1]A[gt \ldots hi-1] is larger than vv.

Proof. We use this invariant, before each test of line L4:

(I) lo≤lt≤i≤gt≤hilo \le lt \le i \le gt \le hi. Each item of A[lo…lt−1]A[lo \ldots lt-1] is less than vv, each item of A[lt…i−1]A[lt \ldots i-1] is equal to vv, and each item of A[gt…hi−1]A[gt \ldots hi-1] is larger than vv.

Start. Line L3 sets lt=i=lolt = i = lo and gt=higt = hi, so the three parts are empty.

Step. Assume (I) and i<gti < gt, and let x=A[i]x = A[i].

  • If x<vx < v (line L5), line L6 swaps A[lt]A[lt] and A[i]A[i]. If lt<ilt < i, the old A[lt]A[lt] was equal to vv, and it moves to index ii; if lt=ilt = i, nothing moves. Now A[lt]=x<vA[lt] = x < v and A[lt+1…i]A[lt+1 \ldots i] are equal to vv. After ltlt and ii grow by one, (I) holds.
  • If v<xv < x (line L7), line L8 makes gtgt one smaller and swaps A[i]A[i] with A[gt]A[gt]. Now A[gt]=x>vA[gt] = x > v, so the large part grows by one item. The new A[i]A[i] came from the unseen part, and ii does not change. Since i<gti < gt held before the step, i≤gti \le gt holds after it, and (I) holds.
  • Otherwise neither x<vx < v nor v<xv < x, so xx is equal to vv in the total order. Line L9 makes ii one larger, and the equal part grows by xx. (I) holds.

End. Each step makes gt−igt - i smaller by exactly one, so the loop stops after hi−lohi - lo steps with i=gti = gt. Then (I) says that the range is the small part A[lo…lt−1]A[lo \ldots lt-1], the equal part A[lt…gt−1]A[lt \ldots gt-1] and the large part A[gt…hi−1]A[gt \ldots hi-1]. The item vv is in the range, and it is neither less than vv nor larger than vv, so it is in the equal part, and lt<gtlt < gt. □\square

Theorem. After THREE-WAY-QUICKSORT(A,lo,hi)(A, lo, hi), the range A[lo…hi−1]A[lo \ldots hi-1] is sorted and holds SS, and no item outside the range changes.

Proof. By strong induction on k=hi−lok = hi - lo. If k≤1k \le 1, line L1 returns, and the range is sorted. Let k≥2k \ge 2, and assume the claim for all shorter ranges. By the lemma, the loop ends with the three parts and lt<gtlt < gt. The ranges [lo,lt)[lo, lt) and [gt,hi)[gt, hi) have fewer than kk items each, because the equal part is not empty. By the hypothesis, line L10 sorts the small part and changes nothing else; it permutes the small part, so its items stay less than vv. Line L11 does the same for the large part. So the range is a sorted part of items less than vv, then items equal to vv, then a sorted part of items larger than vv, and it is sorted. It holds SS, because all moves were swaps inside the range. ■\blacksquare

Termination. Each call on k≥2k \ge 2 items makes two calls on fewer items, and each loop runs kk steps, so the algorithm stops.

Back to Three-way quicksort