Algorithm Search⌘K

Proofs: Binomial heap

These are the human proofs of Binomial heap, at full length.

The operations of a binomial heap keep its invariants and return a minimum full

This proof shows: correctness, termination.

We write K(H)K(H) for the multiset of keys of the heap HH. A list of roots is valid when each of its trees is a binomial tree BkB_k with the min-heap property, the parent pointers inside each tree are right, each root has parent nil, and no two trees have the same order kk. The invariant of a heap is that H.rootsH.roots is valid and H.nH.n is the number of its nodes. The order of a BkB_k is the degree of its root, by property 3 of the representation section.

Lemma 1 (LINK). Let xx and yy be the roots of two heap-ordered binomial trees BkB_k, with x.key≤y.keyx.key \le y.key. After LINK(y,x)(y, x), the tree of xx is a heap-ordered Bk+1B_{k+1} with the same nodes as the two trees, and its children are in increasing order of degree.

Proof. By the definition, a BkB_k with the root of the other BkB_k as a new child of its root is a Bk+1B_{k+1}. Lines L1 and L2 do that and line L3 sets the degree to k+1k + 1. The children of xx had the degrees 0,…,k−10, \ldots, k - 1 in this order, and yy is added last with degree kk. The new edge (x,y)(x, y) is ordered because x.key≤y.keyx.key \le y.key, and the other edges are unchanged. □\square

Lemma 2 (UNION-ROOTS). Let R1R_1 and R2R_2 be valid lists of roots on disjoint sets of nodes. Then UNION-ROOTS(R1,R2)(R_1, R_2) stops and returns a valid list of roots on the union of the two sets of nodes.

Proof. We claim that, before each iteration of line L5 and before each test of line L7, the following hold. (a) Each entry T[d]T[d] is a heap-ordered BdB_d with its root's parent nil. (b) The trees of TT, the tree of the current xx (inside the loop of line L7), and the trees of R1R_1 and R2R_2 not yet visited hold each node of the input exactly once. (c) Inside the loop of line L7, xx is a heap-ordered BdB_d and is not in TT.

At the start, TT is empty and nothing is visited, so (a) and (b) hold. At line L6, the next root xx of degree dd is the root of a heap-ordered BdB_d, so (c) holds. In an iteration of the loop, line L8 takes y=T[d]y = T[d], a heap-ordered BdB_d by (a), out of TT. Line L9 makes x.key≤y.keyx.key \le y.key, and then both xx and yy are roots of heap-ordered BdB_d. By Lemma 1, after line L10 the tree of xx is a heap-ordered Bd+1B_{d+1}, and dd is now d+1d + 1. So (c) holds for the new dd, and (b) holds because the two trees became one. When the test of line L7 fails, T[d]T[d] is empty, and line L11 stores the BdB_d of xx there, so (a) and (b) hold after the iteration.

Each pass of the loop of line L7 links two trees into one, so the number of trees goes down by 1. There are ∣R1∣+∣R2∣|R_1| + |R_2| trees at the start, so there are fewer than ∣R1∣+∣R2∣|R_1| + |R_2| links in total, and the procedure stops. At the end, by (a) and (b), the trees of TT are heap-ordered binomial trees of distinct orders, one for each dd with T[d]≠nilT[d] \ne \text{nil}, and they hold each node once. The parent of each root is nil, because LINK changes only the parent of the root that becomes a child. So the list RR of line L12 is valid. □\square

Union. By Lemma 2, H1.rootsH_1.roots becomes a valid list on the nodes of both heaps, and H1.nH_1.n becomes the sum. So K(H1)K(H_1) becomes the union of the two multisets, and H2H_2 becomes an empty, valid heap.

Insert. Line L14 makes xx a heap-ordered B0B_0. We claim that before each test of line L15, with d=x.degreed = x.degree, the node xx is the root of a heap-ordered BdB_d, the list H.rootsH.roots is valid on the other nodes, and each root in it has degree at least dd. This holds at the start with d=0d = 0. So a root of degree dd, if it exists, is the root of least degree, which is the one that line L15 tests. Lines L16 to L18 remove it and, by Lemma 1, make the tree of xx a heap-ordered Bd+1B_{d+1}. The other roots had distinct degrees larger than dd, so they have degree at least d+1d + 1, and the claim holds again. Each iteration removes a root, so the loop stops. When it stops, each root has a degree larger than dd, so line L19 makes a valid list on the old nodes and xx, with xx of least degree. K(H)K(H) gains the key of xx.

Minimum. Let H.n≥1H.n \ge 1. Each node is in some tree, and by the global form of the heap property, its key is at least the key of the root of that tree. So a root of least key, which line L21 returns, holds a minimum of K(H)K(H).

Extract-min. Let xx be the root that MINIMUM returns, a minimum of K(H)K(H), and let xx be the root of a BkB_k. Line L23 removes it, and the other roots form a valid list on the other trees. By property 3, the children of xx are the roots of heap-ordered binomial trees of the orders 0,1,…,k−10, 1, \ldots, k - 1, which are distinct, and line L24 sets their parents to nil, so RR is a valid list. The two lists have disjoint nodes. By Lemma 2, line L25 makes a valid list on all nodes except xx, and H.nH.n drops by 1. So K(H)K(H) loses one copy of its minimum, which line L26 returns.

Decrease-key. Let k≤x.keyk \le x.key, as line L27 checks. Line L28 lowers the key. No line of DECREASE-KEY changes the shape of a tree, so each tree is still a binomial tree, and the list is valid except for the heap order. We claim that before each test of line L29, the only edge that may not be ordered is the edge (x.p,x)(x.p, x), and that x.p.key≤c.keyx.p.key \le c.key for each child cc of xx when x.p≠nilx.p \ne \text{nil}. This is the condition (U) of the sift-up lemma on the binary heap page, and the proof of that lemma works on each rooted tree: line L30 exchanges the contents of xx and x.px.p, which plays the swap, and line L31 moves up one level. At the start, after line L28, the claim holds because the edges from xx to its children were ordered with the old, larger key, and the old key of xx was at least the key of its parent. Each iteration goes up one level, so the loop stops after at most kk iterations in a BkB_k. When it stops, either xx is a root or the edge (x.p,x)(x.p, x) is ordered, so each edge is ordered. Line L30 moves the items with their keys and updates the handles, so each handle still names the node of its item. K(H)K(H) has the old key replaced by kk.

Delete. Line L32 is a decrease to a key below all others, so by the case above the item reaches the root of its tree, and then this root has the least key, so MINIMUM returns it at line L33, and EXTRACT-MIN removes it. In code, the climb to the root can be done without comparisons, as the Python code does.

Theorem. Starting from empty heaps, after each sequence of operations each heap satisfies its invariant, MINIMUM and EXTRACT-MIN return an item of minimum key, and the multiset of keys of each heap is the one that the meldable priority queue type gives for the same sequence. Each operation stops.

Proof. The empty heap has the empty valid list. Each operation keeps the invariant and changes the keys as the type says, by the cases above, and each stops. ■\blacksquare

Back to Binomial heap