Proofs: Weak heapsort
These are the human proofs of Weak heapsort, at full length.
Weak heapsort sorts the array full
This proof shows: correctness.
Notation. For a node of the tree on the indices , let be the set of indices in the subtree of . The children of are and whatever the bit , so does not depend on the bits; only the names "left" and "right" do, and those of depend only on . The bit is never flipped, because 0 is never the second argument of JOIN; so node 1 is the right child of the root. For a heap of size we only look at the indices below . We use this property of a node :
R(s): for each .
If R(c) holds for the right child of , then and is at least each item of the right subtree of . If R(1) holds, is at least each item of the heap.
Lemma (a join step). Let and , and suppose R(s) holds for each proper descendant of . After JOIN, R(s) holds for and for each proper descendant of . Moreover, for each node outside , if R(s) held before, it still holds.
Proof. Let and be the items at and before the join. Let be the right child of and the left child (either may be missing). Then , so R(c) gives each item of . And is a left child, so the climb from goes through , and ; so R(z) gives each item of .
No swap, so . Nothing changes. Now , and , so R(j) holds. The other statements did not change.
Swap, so . Now , , and is flipped, so is the right child and the left child of . R(j): is at least , at least , and at least . For a proper descendant of , the climb from to changes only if it passes through or as a child of :
- If is on the left spine of , then before the join ; now is a left child, the climb goes on through , and , with .
- If is on the left spine of , then before the join ; now is a right child, so , with .
- Otherwise is a proper descendant of , its item did not change, and does not contain or . So R(s) still holds.
For a node outside : if is not an ancestor of , then contains neither nor (as is an ancestor of , or would contain ) and is neither, except perhaps , where the item only grew. If is an ancestor of , then is not ; if contains the two changed items stay in , and its set of items is the same; if does not contain , then is strictly between and , so , whose item grew, and the item at fell. In each case R(s) still holds.
The build. We claim that after the step of line L3 for , R(s) holds for each . For before the step, there are no nodes above . Each proper descendant of has a larger index, so the lemma applies, and it gives R for and for all its descendants, and keeps R for the other nodes . After , R holds for all nodes, so is a weak heap.
The sort. Suppose that before line L5, R holds for each node of the heap . Then is its largest item, and line L5 puts it at index ; the heap is now . Removing index only shrinks the sets . The item at 0 changed, so R(s) may fail only for the nodes with , which are the nodes of the left spine of node 1 below , the nodes found by line L6. Lines L7 and L8 join with the root in this order. When is joined, its proper descendants are , where R holds by the lemma for the earlier step, and the nodes of its right subtree, whose distinguished ancestors are not 0, so R held for them all along. The lemma applies, and after , R holds for all nodes of .
Theorem. WEAK-HEAPSORT sorts and keeps its items.
Proof. All changes are swaps, so the multiset of items is kept. By the build and by induction over the steps of line L4, each step puts the largest item of at index , and the later steps work only inside . So for each , for . Before line L9, R(1) holds for the heap , so , and the swap orders them. So the array is sorted.