Algorithm Search⌘K

Proofs: Violation heap

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

The violation heap operations keep heap order, the rank rule and the size bound full

This proof shows: correctness.

We use the definitions of the page. A child is active if it is one of the last two children of its parent. A missing child has rank −1-1, and for a node zz with active children z1,z2z_1, z_2, ρ(z)=⌈(r(z1)+r(z2))/2⌉+1\rho(z) = \lceil (r(z_1) + r(z_2))/2 \rceil + 1. The invariants are (1) heap order: every key is at least the key of its parent; (2) the rank rule: 0≤r(z)≤ρ(z)0 \le r(z) \le \rho(z) for every node zz.

Lemma 1 (the pointers). If the sibling lists are as in the representation, then for an active node xx the procedure of lines L11 and L16 returns the parent of xx, and for a node that is not active it returns NIL.

Proof. Let y=x.righty = x.right. If xx is the last child of pp, then y=py = p and p.last=xp.last = x. If xx is the second child from the end, yy is the last child, so y.right=py.right = p and p.last=yp.last = y. If xx is an older child, yy and y.righty.right are siblings of xx, and neither is the last child of the other, since a last child is in the subtree of its parent and siblings are not. For a root, $y = $ NIL. □\square

Lemma 2 (heap order). Every operation keeps (1), and H.minH.min holds a smallest key.

Proof. Insert and meld add roots. In JOIN3, line L1 puts the root of smallest key on top, and the two others become its children, so their keys are at least its key; nothing else changes. In delete-min, the children of zz become roots, which removes the parent relation and so cannot break (1). In decrease-key, the new key of a root has no parent to compare with. If line L11 returns, xx is active and its new key is at least the key of its parent, and the children of xx had keys at least the old key of xx, which is at least the new key. Otherwise xx becomes a root, which keeps (1) for xx and its children. The node z1z_1, a child of xx, has a key at least the old key of xx, which was at least the key of the old parent of xx; so z1z_1 in the place of xx keeps (1). By (1), the root of each tree holds the smallest key of the tree, and every operation sets H.minH.min to a smallest root, either by a comparison with the new root or by a scan of all roots. □\square

Lemma 3 (the rank rule). Every operation keeps (2).

Proof. First, ρ(z)≥⌈(−1−1)/2⌉+1=0\rho(z) \ge \lceil (-1 - 1)/2 \rceil + 1 = 0 for every node, and every rank that the code sets is 00, ρ\rho of a node, or one more than an old rank. So all ranks stay ≥0\ge 0.

ρ(z)\rho(z) depends only on the active children of zz and their ranks. We list the events that change these, and for each we show that (2) holds for zz at the end.

  • A join on zz (line L3). Before it, r(z)=r(z1)=r(z2)=kr(z) = r(z_1) = r(z_2) = k. After it, z1z_1 and z2z_2 are the active children of zz, so ρ(z)=⌈2k/2⌉+1=k+1=r(z)\rho(z) = \lceil 2k/2 \rceil + 1 = k + 1 = r(z). Line L2 changes the order of two children that are no longer active after line L3, so it does not matter for ρ\rho.
  • The children of zz change at line L13. There are two cases. If z=xz = x, line L14 sets r(x)=ρ(x)r(x) = \rho(x) after the change. If zz is the parent of xx and xx was not active, the last two children of zz do not change: xx was older than both of them, and its place either gets z1z_1 or goes away. If zz is the parent of xx and xx was active, then p=zp = z at line L11, and the loop of line L15 first looks at zz.
  • The rank of an active child cc of zz goes down. Ranks go down only at line L16 (at line L14, the node is a root). Line L16 lowers r(p)r(p) and, if pp is active, sets pp to its parent, which by Lemma 1 is zz. So the loop looks at zz next.
  • The rank of zz goes up. This happens only in a join, which is the first case, and at line L14, where it is set equal to ρ(x)\rho(x).

When the loop of lines L15 and L16 looks at a node pp, it either finds ρ(p)≥r(p)\rho(p) \ge r(p), so (2) holds at pp and r(p)r(p) did not change, so no parent sees a change; or it sets r(p)=ρ(p)≥0r(p) = \rho(p) \ge 0, so (2) holds at pp, and the change of r(p)r(p) is an event for the parent of pp, which is looked at next if pp is active and does not matter if pp is not active. The loop goes up one level each time, so it ends. In delete-min and insert no non-root changes its active children, and a node that becomes a root keeps its children. So when an operation ends, every node obeys (2). □\square

Lemma 4 (the paper's Lemma 3). Let zz obey (2), and let its active children have ranks a≥ba \ge b, with −1-1 for a missing child. Then a≥r(z)a \ge r(z), or a=r(z)−1a = r(z) - 1 and b≥r(z)−2b \ge r(z) - 2.

Proof. Since b≤ab \le a, r(z)≤⌈(a+b)/2⌉+1≤a+1r(z) \le \lceil (a + b)/2 \rceil + 1 \le a + 1. If a=r(z)−1a = r(z) - 1, then r(z)−1≤⌈(r(z)−1+b)/2⌉r(z) - 1 \le \lceil (r(z) - 1 + b)/2 \rceil, which needs (r(z)−1+b)/2>r(z)−2(r(z) - 1 + b)/2 > r(z) - 2, that is b>r(z)−3b > r(z) - 3. □\square

Theorem (size bound). If every node obeys (2), the subtree of a node of rank rr has at least Fr+2F_{r+2} nodes, where F1=F2=1F_1 = F_2 = 1 and Fi+2=Fi+1+FiF_{i+2} = F_{i+1} + F_i. So no rank is more than log⁡φn\log_\varphi n, with φ=(1+5)/2\varphi = (1 + \sqrt 5)/2.

Proof. By induction on the height of the subtree. Let zz have rank rr and active children of ranks a≥ba \ge b. If r=0r = 0, the subtree has 1=F21 = F_2 node. Let r≥1r \ge 1. By Lemma 4, a≥r−1≥0a \ge r - 1 \ge 0, so zz has an active child of rank aa. If a≥ra \ge r, that child alone has at least Fa+2≥Fr+2F_{a+2} \ge F_{r+2} nodes by induction, so zz has more. Otherwise a=r−1a = r - 1 and b≥r−2b \ge r - 2. If b≥0b \ge 0, the two children give at least 1+Fr+1+Fr>Fr+21 + F_{r+1} + F_{r} > F_{r+2} nodes. If b=−1b = -1, then r−2≤−1r - 2 \le -1, so r=1r = 1 and a=0a = 0, and zz with its child gives at least 2=F32 = F_3 nodes. In every case the bound holds. Since Fr+2≥φrF_{r+2} \ge \varphi^{r}, a heap of nn nodes has no rank above log⁡φn\log_\varphi n. □\square

Theorem (the operations are correct). Find-min returns a smallest key, delete-min removes and returns a smallest key, and the other operations keep the multiset of keys as the abstract type says.

Proof. By Lemma 2, H.minH.min is a root with a smallest key, which find-min returns. Delete-min removes exactly the node z=H.minz = H.min and keeps all other nodes, since its children become roots and the joins only move roots below roots. Insert adds one node, meld takes the union of the node sets, and decrease-key changes only the key of xx and moves subtrees, so no node is lost. By Lemmas 2 and 3 the invariants hold after each operation, so the next operation starts from a valid heap. ■\blacksquare

Back to Violation heap