Proofs: Parent-pointer tree
These are the human proofs of Parent-pointer tree, at full length.
The parent array keeps its invariant, walks up to the root and gives correct child lists full
This proof shows: correctness.
We use the pseudocode of the page and the invariant:
(P1) For each , is NIL or an index in . (P2) For each , the chain , reaches NIL: there is a with $x_j = $ NIL and are indices.
The forest. Assume (P1) and (P2). The chain of has distinct indices : if with , the chain would repeat forever from and never reach NIL. Hence . Let be the undirected graph on with the edges for the non-roots . Suppose had a cycle . Give each edge the direction ; each vertex has at most one outgoing edge. A cycle in which each vertex has at most one outgoing edge among its two cycle edges, with vertices and edges, has exactly one outgoing edge at each vertex, so its edges form a directed cycle, and following parents from a vertex of goes around forever, against (P2). So is a forest. Each non-root is joined to the root at the end of its chain, so the components of are in bijection with the roots, and is a tree when there is exactly one root.
A new tree. The array with meets (P1) and (P2).
ADD-CHILD. Let (P1) and (P2) hold for , and let . Line L1 sets , and line L2 sets and . (P1) holds for the old entries, which are unchanged and lie in , and for , since is an index. For (P2), no old entry equals , so the chain of an old vertex never reaches ; it is the same chain as before and reaches NIL in at most steps. The chain of is followed by the chain of , which reaches NIL in at most steps, so the chain of reaches it in at most steps. So (P1) and (P2) hold after the call, and the tree of has gained the leaf as a child of .
PATH-TO-ROOT. Lines L4 to L6 set to and report each while NIL. By (P2) the loop stops after reports, and it has reported , the path from to the root of its tree in . Each loop pass costs , so the time is , where .
CHILD-LISTS. Call a child of when , and let be the number of children of . By (P1) each non-root has exactly one parent in .
After line L8: and for , since line L8 adds 1 to once for each non-root , and nothing else changes .
After line L9: for . The loop keeps the claim "for , , and for ", which holds at and is carried from to by . In particular is the number of non-roots, the length of , and the intervals have length and partition .
Lines L10 to L14: Line L10 sets . We claim that before the pass of line L11 for , for each , , and the positions hold the children of in increasing order. This holds before . In the pass for , if is a root nothing changes and the claim carries over. Otherwise, with , line L13 writes at position , which is less than because has at least one child , namely , not yet placed; and line L14 increments . The written position lies in , so no other block is touched, and follows the smaller children of . So the claim holds for .
After the pass for , each holds exactly the children of in increasing order, so is the list of children of , as line L15 returns. Lines L7, L8, L9 and L10 each take time, and lines L11 to L14 take , so CHILD-LISTS runs in time with words of output.