Root a finite tree, and let be the optimum vertex cover sizes of a descendant subtree conditional on excluding or including its root. Excluding a parent forces all children to be included; including it permits either child state. These facts prove the displayed recurrences by structural induction. Empty child sums give at a leaf of a rooted tree. Evaluating in postorder traversal and taking the smaller root state gives a linear-time dynamic programming algorithm.
Use the usual bottom-up splaying operations. We prove the stronger result that at most three successful calls suffice. No insertions or deletions are needed.
If the chosen key is the minimum stored key, first perform splaying on and then on its immediate successor. The argument for consecutive keys in a binary search tree makes the left child of the successor with an empty right subtree; minimality makes its left subtree empty too. Hence is a leaf of a rooted tree. The maximum-key case is the mirror image.
Suppose is an interior key. Since at least four keys are stored, there are either two keys larger than or two smaller than . In the former case choose four consecutive stored keys
where is the predecessor of , and are the next two successors. Perform .
Here is a complete check of the local shapes. After the first call, is the root. After the second, is the root; every key below is in its left subtree , and every key above stays in the right subtree of . These outside subtrees cannot interfere with the next search. Between and there are only . The last step of splaying on is either a zig step, leaving as its right child; a zig-zag step, with the same result; or a zig-zig step, leaving some as its right child with immediately to the right of . Consequently the possible right subtrees of are exactly among these four forms, using for a node with its left and right subtrees:
Here an unexpanded or denotes a node with no children. Each row follows by the indicated one or two tree rotations in each bottom-up step. All rows end with as the right child of , with both its subtrees empty. If instead two keys below are available, reflect the construction, exchanging left and right and reversing the order of keys. This proves splaying a chosen node into a leaf for every node of every splay tree of size at least four.
Root the tree arbitrarily. For each vertex , let be the minimum vertex cover size in its descendant subtree, conditional on selecting , and the corresponding minimum conditional on omitting . Process the vertices in postorder traversal. For every child of ,
At a leaf of a rooted tree, the empty sums give . Return at the root .
For algorithm correctness, if is selected, each child subtree may independently use its cheaper state, since the connecting edge is already covered by . If is omitted, each child must be selected to cover its connecting edge. Distinct child subtrees have no edges between them because the input is a tree. These observations prove the recurrences by structural induction. Each edge contributes constant work once, giving time complexity and space with adjacency lists. The single-vertex tree correctly has optimum zero. This is minimum vertex cover of a tree by dynamic programming.
We construct an injection from the unmatched vertices in a matching to the leaves of a rooted tree. Start a downward graph path at each unmatched vertex . If the current vertex is a leaf of a rooted tree, stop. Otherwise choose any child . The current vertex is either the unmatched starting point or a vertex already matched to its own parent.
In either case, cannot be unmatched: the proper matching in a rooted tree condition would require its parent to be matched to one of 's siblings in a rooted tree, whereas that parent is either unmatched or already matched upward. Nor can be matched to its parent. Its matching partner must therefore be one of its own children, say . Extend the graph path by the two edges to and then to , and continue from .
Every extension descends two levels, so finiteness guarantees termination at a leaf of a rooted tree. Every visited vertex except the starting point is matched. The constructed graph paths for different unmatched starting points are disjoint: if two downward graph paths in a tree meet, one starting point must lie on the other path, which would put a second unmatched vertex after the first. That is impossible. Hence their terminal leaves of a rooted tree are distinct, proving
Only the properness condition for unmatched non-root vertices was used. If the root is unmatched and the convention exempts it because it has no parent, the same construction starts there and still works. Thus the root convention does not affect the claimed inequality. This proves the unmatched-vertex bound for a proper tree matching without requiring to have maximum size.
In executable Haskell, the algebraic data type declaration uses data, rather than the printed type. A leaf of a rooted tree contributes False; a fork contributes True followed by its left and right subtrees in that order.
data Tree = Leaf | Fork Tree Tree

preorder :: Tree -> [Bool]
preorder Leaf       = [False]
preorder (Fork l r) = True : (preorder l ++ preorder r)
This is a preorder traversal of a full binary tree, including the leaves. Structural induction proves correctness: the leaf of a rooted tree case has precisely one output, and the fork case concatenates the correct preorder traversals of its two subtrees after its own marker.
An equivalent version avoids repeatedly copying the left list through list concatenation:
preorder t = walk t []
  where
    walk Leaf rest       = False : rest
    walk (Fork l r) rest = True : walk l (walk r rest)
Its strengthening is walk t rest = preorder t ++ rest. Each vertex constructs one list cell, so this version has linear time complexity. The concise result is
For parts (b)–(e), use array indices as tree handles. This also makes the shared storage in part (d) type-correct: both pending handles and output markers occupy integer cells. Zero denotes a leaf of a rooted tree; a positive handle denotes a fork whose children are in nodes[t-1]. Only finite acyclic structures are admitted. An allocated fork's children are themselves valid handles.
CONST MaxForks = 100000;
TYPE Tree = INTEGER;
     Node = RECORD left, right: Tree END;
     Arena = ARRAY MaxForks OF Node;
VAR nodes: Arena;
    used: INTEGER;

PROCEDURE NewFork(left, right: Tree): Tree;
BEGIN
  ASSERT(used < MaxForks);
  nodes[used].left := left; nodes[used].right := right;
  INC(used);
  RETURN used
END NewFork;

PROCEDURE Preorder(t: Tree; VAR out: ARRAY OF INTEGER;
                   VAR count: INTEGER);
  PROCEDURE Visit(p: Tree);
  BEGIN
    IF p = 0 THEN
      out[count] := 0; INC(count)
    ELSE
      out[count] := 1; INC(count);
      Visit(nodes[p-1].left); Visit(nodes[p-1].right)
    END
  END Visit;
BEGIN
  count := 0; Visit(t)
END Preorder;
Initialize used := 0 before constructing any trees; NewFork allocates within this arena. The fixed capacity is an implementation parameter and may be replaced by a dynamically allocated arena. The returned prefix out[0..count) encodes Boolean values by and . This encoding is part of the chosen representation, not a conversion of a pointer into a Boolean value.
The recursion invariant is that Visit(p) appends exactly the preorder traversal of the subtree represented by p. If the full binary tree has forks, it has leaves; hence
Each occurrence is visited once, using linear time complexity and a call stack bounded by the height of a binary tree. The arena is the input representation, not an extra copy made by the traversal.
Use an explicit stack of handles. Push the right subtree first, so that the left subtree is removed first by the LIFO stack.
PROCEDURE PreorderIter(t: Tree; VAR out: ARRAY OF INTEGER;
                       VAR count: INTEGER;
                       VAR stack: ARRAY OF Tree);
VAR top: INTEGER; p: Tree;
BEGIN
  count := 0; top := 1; stack[0] := t;
  WHILE top > 0 DO
    DEC(top); p := stack[top];
    IF p = 0 THEN
      out[count] := 0; INC(count)
    ELSE
      out[count] := 1; INC(count);
      stack[top] := nodes[p-1].right; INC(top);
      stack[top] := nodes[p-1].left; INC(top)
    END
  END
END PreorderIter;
The loop invariant says that the already written prefix, followed by the preorder traversals of the pending subtrees in top-to-bottom stack order, equals the entire required output. Popping a leaf of a rooted tree transfers one marker to the prefix. Popping a fork transfers its marker and replaces its remaining work by left then right subtree work. Both preserve the loop invariant. The number of as-yet-unwritten vertices decreases by one per iteration, proving termination.
The time complexity is linear in the output length. The maximum stack size is at most one plus the height of a binary tree.
Every node of a splay tree with at least four distinct keys can become a leaf of a rooted tree using only successful splaying operations. At an extreme key, access that key and then its sole adjacent stored key; the consecutive keys in a binary search tree property makes the extreme key a leaf. For an interior key with two larger stored keys, take consecutive and access ; the mirror construction handles two smaller keys.
For a quick shape proof, use for a node and its two subtrees. After accessing , the right subtree of can only be , , , or , with outside subtrees below and above . This follows by inspecting the final zig step, zig-zig step or zig-zag step that moves above the former root . In each case, accessing yields , where is a leaf and denotes an empty subtree. These rotations prove the bound for arbitrary outside subtrees.