Proofs: Binary heap
These are the human proofs of Binary heap, at full length.
The operations of a binary heap keep the heap invariant and return a minimum full
This proof shows: correctness, termination.
We write for , for the parent of , and for the set of children of that exist, a subset of that holds only indices at most . An edge is a pair with , and it holds when . The invariant (H) says that each edge holds. Each operation changes only by swaps and by the writes of lines L12, L18 and L23, which we follow one by one.
Lemma 1 (sift-up). Let . Assume
(U) each edge with holds, and if , then for each .
Then SIFT-UP stops after at most iterations, permutes the keys of , and after it (H) holds.
Proof. We show that (U) is a loop invariant of line L1 for the current . It holds at the start by assumption.
Maintenance. Let the test of line L1 be true, so and, with , . Line L2 swaps them, so afterwards and . We check each edge that has or as an end, other than the edge into , which (U) for the new value excludes.
- The edge : , since .
- The edges for : the second part of (U) gave before the swap, and did not change.
- The edge for the other child of , if it exists: the edge held before, so , and now .
No other edge has an end at or , except the edge when . So after line L3 sets , each edge except the one into the new holds. For the second part of (U) at the new : the edge held before the swap, because (U) excluded only the edge into the old , so . The children of now hold (at the old ) and . So is at most each child of .
Termination. Each iteration replaces by , so drops by exactly 1, and the test fails after at most iterations. When the loop stops, either , and then (U) says that each edge holds because the root has no edge into it, or , and then the one excluded edge holds too. In both cases (H) holds. Each change is a swap, so the keys are permuted.
Lemma 2 (sift-down). Let . Assume
(D) each edge with holds, and if , then for each .
Then SIFT-DOWN stops after at most swaps, where is the height of , permutes the keys of , changes only the cells of the subtree of , and after it (H) holds.
Proof. (D) is a loop invariant of line L4. It holds at the start by assumption. In an iteration, lines L5 to L7 set to an index of a smallest key among and for : line L6 compares with , and line L7 compares with the smaller of the two, and each test is done only for a child that exists.
Stop. If , then for each , so the edges out of hold, and with (D) each edge holds: (H) is true, and line L8 returns.
Maintenance. If , let and , so and for the other child of . Line L9 swaps them. We check the edges with an end at or , except the edges out of , which (D) for the new value excludes.
- The edge : .
- The edge : .
- The edge if : the second part of (D) gave , because , and is now .
For the second part of (D) at the new : its parent is the old , which now holds , and each child of had before the swap, because the edges out of were not excluded by (D). So line L10 keeps (D).
Termination. Each swap moves to a child, so the depth of grows by exactly 1. A node of the subtree of the first has depth at most below it, so there are at most swaps, and after them the next iteration stops at line L8 or finds no child. The changed cells are and its descendants.
Insert. Before line L11, (H) holds on . Lines L11 and L12 add the cell with the key . Each old edge holds, and the new node has no children. So (U) holds with , and Lemma 1 gives (H) on the new heap, whose keys are the old keys and .
Find-min. By (H) and the global form of the heap property, for each , because the root is an ancestor of each node. So line L15 returns a minimum. Nothing changes.
Extract-min. Let and let , a minimum by the claim on find-min. Lines L18 and L19 write the last key into the root and drop the cell , so the keys of are the old keys with one copy of removed. If , the heap is empty and (H) holds. Else each edge with is an old edge between two unchanged cells, so it holds, and the root has no parent. So (D) holds with , and Lemma 2 gives (H). Line L21 returns .
Decrease-key. Let , as line L22 checks, and let before line L23. Each edge not into and not out of is unchanged. The edges held with , and , so they still hold. If , then for each , by the old edges. So (U) holds, and Lemma 1 gives (H). The keys are the old keys with replaced by .
Build. We claim that, before the iteration of line L26 for , the subtree of each index is a heap, that is, each edge inside that subtree holds. At the start , and each is a leaf, whose subtree has no edges. In the iteration for , the subtrees of the children of have indices larger than , so they are heaps. Consider the subtree of alone as a heap with root : the only edges that may fail are the ones out of , and has no parent inside it. So (D) holds for it, and by Lemma 2 the subtree of becomes a heap. Now take an index , so that the claim must hold for the next iteration. If is in the subtree of , its subtree is part of a heap, so it is a heap. Else the subtree of is disjoint from the subtree of : an index is not an ancestor of , because an ancestor has a smaller index. Lemma 2 says that only cells of the subtree of change, so the subtree of is unchanged and stays a heap. When the loop ends with , the subtree of is the whole tree, and (H) holds. Each step is a swap, so the keys of are the keys of .
Theorem. If (H) holds before an operation, it holds after it; FIND-MIN and EXTRACT-MIN return a minimum key of the heap; and each operation changes the multiset of keys exactly as the priority queue type says (insert adds , extract-min removes one minimum, decrease-key replaces the key at by , build makes the multiset of ). Each operation stops.
Proof. The claims above, for each operation, together with Lemmas 1 and 2.