Proofs: Smoothsort
These are the human proofs of Smoothsort, at full length.
Smoothsort sorts the array in place full
This proof shows: correctness.
Definitions. A Leonardo tree of order at root index occupies . For it is the node . For its children are , the root of a tree of order , and , the root of a tree of order ; the sizes add up, since . The tree is a heap when each node is at least each of its children. A forest is a list of trees whose segments are consecutive from index 0. We use two invariants for a forest:
- (H) each tree is a heap;
- (R) the roots are non-decreasing from left to right.
Lemma 1 (SIFT-DOWN). If both subtrees of a tree are heaps, SIFT-DOWN of its root makes the tree a heap and only permutes its segment.
Proof. This is the sift-down of heapsort, on a tree whose children are given by the formulas above. Each swap exchanges the root with its larger child when the root is smaller; then the old child position holds a value that is at least the other child and its own former subtree, except at the new position of the moving item, where the claim is applied again on a smaller tree. When the loop stops, the moving item is at least its children.
Lemma 2 (RECTIFY). Suppose the trees before tree satisfy (H) and (R), and the two subtrees of tree (if any) are heaps. Then after RECTIFY, the trees up to tree satisfy (H) and (R).
Proof. Let be the current tree, starting with , with root and, if the order is at least 2, children and . Let be the largest of , and . The loop keeps this claim: the trees before satisfy (H) and (R); the subtrees of are heaps; and each tree after , up to , is a heap whose root is at least all items of the trees to its left and at least the roots before it. At the start there are no trees after , so the claim holds.
If the root of tree is greater than , the loop swaps and . Now the root of is , which is greater than and , so tree is a heap. Since was the largest item of the heap , and the roots before are at most by (R), the new root of tree is at least all items to its left. Tree now has root and subtrees that are heaps, so the claim holds with as the current tree.
If , or is the first tree, the loop stops, and SIFT-DOWN makes tree a heap by Lemma 1. Its root is now , the largest item of the tree, and , so (R) holds between and . Between and : the root of was set to a root that was larger than all items of tree at that time, and tree has the same items now. So (R) holds for all trees up to .
Lemma 3 (the build step). If the forest of satisfies (H) and (R), then after lines L3 to L5 the forest of does.
Proof. If line L3 joins trees of orders and , they occupy , and with the root they form a tree of order in the layout above, with heaps as subtrees. If line L4 adds a single node, it is a tree with no subtrees. In both cases the earlier trees are unchanged, so Lemma 2 applies with the last tree.
Lemma 4 (the removal step). If the forest of satisfies (H) and (R), then is the largest item of , and after lines L7 to L9 the forest of satisfies (H) and (R).
Proof. By (H), each root is the largest item of its tree, and by (R) the last root is the largest root. The last root is at index , the right end of the prefix. Removing it leaves either no new tree () or its two subtrees, which are heaps and occupy the end of the prefix in the order left, right. Lemma 2 applied to the left subtree, whose own subtrees are heaps, gives (H) and (R) up to it; then Lemma 2 applied to the right subtree gives them for the whole forest.
Theorem. After SMOOTHSORT, the array is sorted, and it holds the input items.
Proof. All changes are swaps, so the multiset of items is unchanged. By Lemma 3 and induction on , after the build the forest of satisfies (H) and (R). By Lemma 4 and induction downwards on , at each step of line L6 the item is the largest of , and it is not moved again, because all later steps work inside . So for each , is at least each item before it, and the array is sorted.