Algorithm Search⌘K

Proofs: Hollow heap

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

The hollow heap operations keep the heap order and find the minimum full

This proof shows: correctness, termination.

We use the notation of the page. The child list of a node xx starts at child(x)\mathit{child}(x), follows the sibling pointers, and ends at nil or right after the first node uu with ep(u)=x\mathit{ep}(u) = x. An edge goes from xx to each node of its child list. A heap with root hh satisfies the following invariants.

  • (G) The nodes and edges form a finite acyclic graph in which every node is a descendant of hh.
  • (P) Each node other than hh has one or two parents. A node uu with two parents is hollow, ep(u)\mathit{ep}(u) is one of them, uu is the last node of the child list of ep(u)\mathit{ep}(u), and its sibling pointer continues the child list of the other parent. A node with one parent, or none, has ep=nil\mathit{ep} = \mathrm{nil}.
  • (O) For each edge from xx to yy, key(x)≤key(y)\mathrm{key}(x) \le \mathrm{key}(y).
  • (R) The heap is empty, or hh is full.
  • (I) For each item ee in the heap, node(e)\mathrm{node}(e) is a full node whose item is ee; each full node holds an item of the heap.

Lemma 1. If (G), (O), (R) and (I) hold, the item of hh has the minimum key.

Proof. Each item is in a full node by (I), which is a descendant of hh by (G). The keys do not decrease along each path from hh, by (O). □\square

Lemma 2. LINK(v,w)(v, w) of two roots of disjoint heaps returns a root whose descendants are those of vv and ww, and keeps (O), (P) and (G).

Proof. The loser ℓ\ell becomes the first child of the winner mm: its sibling pointer is set to the old first child of mm, so the child list of mm gains ℓ\ell at its front and keeps its old end. The only new edge goes from mm to ℓ\ell, with key(m)≤key(ℓ)\mathrm{key}(m) \le \mathrm{key}(\ell) by the test of line L1. ℓ\ell was a root, so it now has one parent, and its ep\mathit{ep} is nil by (P). No cycle is made, since mm is not a descendant of ℓ\ell in disjoint heaps. □\square

Insert, meld and decrease-key

INSERT makes a full node of rank 0 with no children and links it with hh; MELD links two roots. By Lemma 2 the invariants hold, and the new root is full, since both roots were full.

DECREASE-KEY(e,k)(e, k) with k≤key(node(e))k \le \mathrm{key}(\mathrm{node}(e)). If u=node(e)u = \mathrm{node}(e) is the root, setting its key keeps (O), since the key went down and the root has no parents. Else uu is full and is not the root, so by (P) it has one parent and ep(u)=nil\mathit{ep}(u) = \mathrm{nil}. Lines L8 to L11 make vv with the item ee and the key kk, make uu hollow, and make uu the only node of the child list of vv, with ep(u)=v\mathit{ep}(u) = v; the sibling pointer of uu still continues the list of its first parent. So uu has two parents and meets (P). The new edge from vv to uu has k≤key(u)k \le \mathrm{key}(u), and the key of uu is unchanged, so (O) holds. Now ee is in the full node vv only, which gives (I). vv is a root, and line L12 links it with hh, so by Lemma 2 (G) holds again. The new root is hh or vv, both full.

Delete

Line L13 makes node(e)\mathrm{node}(e) hollow and removes ee, which keeps (I), (G), (O) and (P). If hh is still full, (R) holds and we are done. Else the loop runs. Call a node destroyed if it enters HH. The loop keeps the following.

(L1) Each node in HH, or destroyed, is hollow and has no parent that is not destroyed. (L2) Each node yy that is not destroyed has a parent that is not destroyed, or is a full root in a tree of a root in AA, and each node of a tree of AA that is not a root of AA has one parent. (L3) For a node uu that is not destroyed, ep(u)\mathit{ep}(u) is nil or a node that is not destroyed, and (P) holds for uu with respect to its parents that are not destroyed, except that uu may still be in the list of the node xx under scan.

The cases of a child uu of xx. The node xx is hollow and all its parents are destroyed, by (L1).

  • uu is full. By (P), uu has the one parent xx. It becomes a root. Each ranked link in line L22 links two roots of trees in AA, which are disjoint, so by Lemma 2 the result is a tree with a full root that is again in AA and (O) holds on the new edge. So (L2) holds for uu.
  • uu is hollow and ep(u)=nil\mathit{ep}(u) = \mathrm{nil}. By (P) and (L3), xx was its only parent that is not destroyed, so it has none now, and line L19 puts it into HH, which keeps (L1).
  • uu is hollow and ep(u)≠nil\mathit{ep}(u) \ne \mathrm{nil}. Then uu has two parents, xx and yy. If ep(u)=x\mathit{ep}(u) = x, then uu is the last node of the list of xx, so the scan stops; its sibling pointer continues the list of yy, and with ep(u)=nil\mathit{ep}(u) = \mathrm{nil} it now has the one parent yy, as (P) asks. If ep(u)=y\mathit{ep}(u) = y, then xx is the first parent; setting the sibling pointer of uu to nil ends the list of yy at uu, as before, and with ep(u)=nil\mathit{ep}(u) = \mathrm{nil} it has the one parent yy. The scan of xx goes on with the sibling read before the change.

So the scan of xx visits every node of its child list. After it, xx is destroyed and no node that is not destroyed points to it as a parent: every child of xx was handled above.

After the loop. HH is empty. Let yy be a node that is not destroyed. Walk from yy to a parent that is not destroyed, while there is one. The walk ends, by (G), at a node zz with no parent that is not destroyed. If zz were hollow, then when the scan of its last destroyed parent reached it, its ep\mathit{ep} was nil, and it entered HH, so it was destroyed; this is false. So zz is full, and it is a root of a tree in AA or below one, by (L2). Hence every node that is not destroyed is in a tree of a root of AA, and in particular so is every full node, since destroyed nodes are hollow by (L1). The links of lines L25 and L26 join the roots of AA into one tree, by Lemma 2, whose root is full, being a root of AA. If AA is empty, no full node is left and the heap is empty. So (G), (O), (P) and (R) hold, and (I) holds, since no full node was changed.

DELETE-MIN reads the item of hh, which is a minimum by Lemma 1, and deletes it.

Termination

INSERT, MELD and DECREASE-KEY do a constant number of steps. In DELETE, a node enters HH only when the scan of its last remaining parent reaches it, and a scanned node is destroyed, so each node enters HH at most once and the outer loop runs at most once per node of the finite graph. Each child list is finite and is scanned once. Each iteration of the inner loop of line L21 removes one root from AA, so it runs at most ∣A∣|A| times. The final loop runs once per root in AA. So every operation ends.

Together with Lemma 1, the invariants show that FIND-MIN and DELETE-MIN return an item of minimum key, and that each operation leaves a valid hollow heap that holds exactly the items inserted and not yet deleted, with their current keys. ■\blacksquare

Back to Hollow heap