Definition · PartitionTo partition a[lo..hi] around a pivot value p drawn from it is to rearrange the subarray so that p sits at some index q with a[lo..q−1] ≤ p and a[q+1..hi] > p. The index q is returned; it is not chosen in advance and is not generally the middle.
Lomuto's scheme is the one this course counts. Swap the chosen pivot to the end of the subarray, walk j from lo to hi − 1, and keep a second index i marking the end of the at-most-pivot region. That is the whole algorithm, and the pseudocode of it is four lines in the block above.
Definition · Loop invariantA loop invariant is a statement about the program's state that is true before the loop begins, and true after each iteration if it was true before that iteration. It is useful when its truth at the loop's exit, together with the exit condition, gives the postcondition you wanted.
The invariant here is the three regions. It holds before the loop because two of the regions are empty. It is preserved by each step, in the two cases the concept card gives. And at exit j = hi, so the unexamined region is empty and the array is exactly at most | above | pivot, one swap away from what was wanted.
Theorem · Partition places the pivotWhen the loop exits, swapping a[i+1] with a[hi] leaves the pivot at index i + 1 with every element of a[lo..i] at most it and every element of a[i+2..hi] above it. The pivot is therefore at its final position in the sorted array.
At exit the invariant gives a[lo..i] ≤ p and a[i+1..hi−1] > p, with the pivot itself still at hi.
The final swap exchanges the pivot with a[i+1], which is above the pivot, so it lands in the region of elements above the pivot, where it belongs. The pivot lands at i + 1. Every element to its left is at most it and every element to its right is above it, which is the definition of that position being its place in sorted order — and that is a property of the final array, not of this pass, so no later recursion can disturb it.
□
Example · Twelve elements, pivot 24The array is 38 27 43 3 9 82 10 55 16 7 91 24 and the pivot is the last element, 24. Eleven comparisons and six swaps later the array is 3 9 10 16 7 24 43 55 38 27 91 82, with the pivot at position six. Five elements are at most 24 and six are above it, and neither group is in order. The worked example below steps through all eleven comparisons.
Hoare's scheme, and what it buys
Hoare's partition walks one index up from the left and one down from the right, swapping an out-of-place pair whenever both stop, and finishes when the indices cross. It does about a third as many swaps as Lomuto on typical data — four rather than six on the lab's array — and it does not place the pivot at a known index; it returns a boundary. Its comparison count is data-dependent, which is why the clean n − 1 above is stated for Lomuto and not for partition in general.
Both schemes send keys equal to the pivot to one side. That sounds like a detail and it is the subject of a counterexample two lessons from here: on an array whose keys are all equal, Lomuto splits n into 0 and n − 1 under every pivot rule there is, including a randomised one.
Two things are worth checking in the lab's step table. The i and j columns count from zero, which is why i starts at −1: the at-most region is empty, and an index one before the start is how that is said. And the invariant column is evaluated on the array at that step rather than assumed, so a broken invariant would appear as the word BROKEN and not as a missing row.