Proofs: Linked-list merge sort
These are the human proofs of Linked-list merge sort, at full length.
Bottom-up linked-list merge sort sorts the list stably and stops full
This proof shows: correctness, termination.
Let the input list have nodes. Write for "node came before node in the input". A sequence of nodes is stably sorted when its keys are non-decreasing and nodes with equal keys appear in the order .
Lemma 1 (one merge). Let lines L6 to L11 start with at the first node of a stably sorted run of nodes, followed in the list by a stably sorted run of nodes, where is the number of nodes after , and let each node of come before each node of in . Then the loop of line L8 appends the nodes of and to , each exactly once, as a stably sorted sequence, and ends with at the first node after , or nil.
Proof. Line L6 walks nodes, so is the first node of , and where is the number of nodes from on. Each step of the loop of line L8 takes the first remaining node of (line L10) or of (line L9) and appends it (line L11). The counters and count the remaining nodes of and the nodes of that may still be taken, and says that has nodes left when . So the loop runs while either run has nodes left, and takes each node once. It takes from only when is empty or the head of has a strictly smaller key than the head of . By induction on the steps, the appended sequence is the stable merge: the node appended is a minimum of the remaining keys, because the heads of the two sorted runs are their minima; and among equal keys a node of is taken before a node of , which matches , while the order inside each run is kept. When both runs are used up, is the node after .
Invariant (B). At the test of line L2 for width , the list from holds all input nodes, linked in a line that ends with nil, and for each the block of nodes at the positions is stably sorted, and every node of block comes before every node of block in .
Initialization. For , each block has one node, and the list is the input list in input order.
One pass. The loop of line L4 starts with at block 0. By Lemma 1, the first merge appends blocks 0 and 1 as a stably sorted sequence, and leaves at the start of block 2, which line L12 copies to . The next merge handles blocks 2 and 3, and so on, until is nil. The nodes of different pairs are appended in the order of the pairs, and by (B) all nodes of pair come before all nodes of pair in . Line L13 ends the new list. So after the pass the list holds all nodes, and its blocks of nodes are the merged pairs, each stably sorted, in the order between blocks. Line L15 sets to , so (B) holds at the next test of line L2.
Termination. A pass with width makes merges rounded up, that is , because each merge consumes two blocks, or one at the end. This is at most 1 exactly when . Since doubles in each pass, a pass with comes after at most passes, or 1 pass when . Each inner loop stops: line L6 makes at most steps, the loop of line L8 appends one node per step and there are finitely many, and the loop of line L4 moves forward past at least one node per merge.
Correctness at the end. Line L14 returns after a pass with . As , it made exactly one merge, of block 0 and block 1 of width , which together hold all nodes. By Lemma 1 the list from is all nodes, stably sorted, and line L13 ended it with nil.