Proofs: American flag sort
These are the human proofs of American flag sort, at full length.
American flag sort sorts strings in lexicographic order full
This proof shows: correctness, termination.
Let for and otherwise. A task is valid if the strings of have length at least and agree on their first characters.
Fact 1. Let and agree on their first characters, with . If then . If then . If then they agree on characters. (This is Fact 1 of MSD radix sort, with the same proof.)
Lemma (one step). Let a task with be popped. After lines L5 to L11, the range is a permutation of its old content, and for each the block holds exactly the strings with .
Proof. The blocks are disjoint and cover , in the order of , because and . We show that the following holds before and after each execution of lines L9 to L11:
(P1) for each , , and holds strings of bucket ; (P2) for each , the number of strings of bucket at positions outside is , and these positions are all in blocks at positions in ; (P3) the range is a permutation of its old content.
At the start , so (P1) holds; there are strings of bucket , so (P2) holds; and (P3) holds.
In the scan of bucket , let and . If , line L10 extends block by a string of bucket , and (P1) to (P3) still hold. If , the string at is an unplaced string of bucket , so by (P2) and . Line L11 swaps it into position and then increases . Block grows by a string of bucket , so (P1) holds for ; the string that moved to was at an unplaced position, and is still unplaced in block , so (P1) holds for and (P2) holds for every bucket. A swap keeps (P3).
Each execution of lines L9 to L11 increases by 1, and this sum is at most , so the loops end, after at most executions. When the scan of bucket ends, , and never decreases. So at the end for all , and by (P1) each block holds only strings of its bucket.
Correctness. Call the state good if the tasks on have disjoint ranges and are valid, every pair of indices that are not in the same task has , and holds the input strings. The first task makes the state good. When a task with at most one string is popped, nothing changes and the state stays good. When a task with strings is popped, the lemma gives blocks in the order of .
- Two strings in different blocks are in order by Fact 1.
- Two strings in block 0 are equal by Fact 1.
- Each block with at least two strings becomes a task, valid at by Fact 1. A block with one string has no partner.
- Pairs with one index outside keep their relation, because the range holds the same strings as before.
So the state stays good.
Termination. Let be the largest length of a string. A valid task with at least one string has . Give a task the weight , as in the proof for MSD radix sort. A pop of a task with strings replaces its weight by children of total weight at most , so the total weight drops by at least , and other pops do not increase it. So the number of pops of tasks with two or more strings is at most . Line L12 pushes only tasks with at least two strings, so every pop after the first is of such a task, and the loop ends.
Result. When is empty, every pair has , and holds the input strings, so is sorted.