Proofs: Dual-pivot quicksort
These are the human proofs of Dual-pivot quicksort, at full length.
Yaroslavskiy's partition splits the range into three parts, and dual-pivot quicksort sorts full
This proof shows: correctness, termination.
Fix a call PARTITION with . Every change of is an exchange of two positions in , so the multiset of never changes, and no position outside the range changes. After line L8, , and these two positions are not touched by the loop, because all exchanges of lines L12, L15 and L17 use positions , and , which stay in , as the invariant shows.
Invariant. At each test of line L10:
(P) , , and , and (a) each item of is less than ; (b) each item of is at least and at most ; (c) each item of is at least .
Initialization. and , so all three zones are empty, and because .
While , the zone (b) is , and is the unseen zone.
Maintenance. Assume (P) and , and let .
Case 1, (lines L11, L12). If , then is a middle item by (b), and the exchange puts at and the middle item at . If , the exchange does nothing. Then and grow by 1 (line L18). Zone (a) gains , and zone (b) moves one place right with the same items. (P) holds.
Case 2, (the tests of L11 and L13 both fail). Only grows, and zone (b) gains , with . (P) holds.
Case 3, (line L13). The loop of line L14 moves left while and . Each position it passes holds an item greater than , so it can join zone (c). It stops at some with or . Line L15 exchanges and and sets . Now , which is the old if or itself if , is at least , so zone (c) is after the decrement, and (c) holds. The new is the old . If it is again, line L16 does not move it because , and line L18 makes . Then , so zone (b) is the same as before the step, and is in zone (c). (P) holds, and the loop ends. If , the new is at most . Line L16 tests it: if it is less than , line L17 moves it into zone (a) as in Case 1; otherwise it is between and and joins zone (b) when line L18 increments . In this subcase after line L15, so after line L18 , and (P) holds.
Termination. In each iteration, drops by at least 1, because grows by 1 and never grows. So the loop ends, with or .
The result of PARTITION. At the end, , so zone (b) is , and the zones (a), (b), (c) cover . Line L19 sets and . Now is the last item of zone (a), or itself if zone (a) is empty, and is the first item of zone (c), or itself if zone (c) is empty. Line L20 exchanges with : the item less than goes to , inside the left part, and goes to . Likewise goes to , and the item at least goes to . So:
, , , each item of is less than , each item of is between and , and each item of is at least .
Here because before line L19, so .
DUAL-PIVOT-QUICKSORT sorts. By induction on . For , line L1 returns, and the range is sorted. For , line L2 only exchanges items inside the range, and PARTITION returns as above. The ranges , and do not contain or , so each has fewer than items, and by induction the three calls sort them. Each call changes only its own range, so the order relations above still hold: every item left of is less than , every item between and is in , and every item right of is at least . Together with the sorted parts this makes non-decreasing.
Termination. Each call either returns at line L1 or makes three calls on strictly shorter ranges, and PARTITION ends. So the recursion is finite, whatever the random choices of line L2.