Algorithm Search⌘K

Proofs: Preorder traversal

These are the human proofs of Preorder traversal, at full length.

The stack-based preorder traversal lists the tree in preorder full

This proof shows: correctness, termination.

Let TT be an ordered tree rooted at rr, with child lists C[v]C[v]. Write pre(Tv)\mathrm{pre}(T_v) for the preorder of the subtree of vv, and pre−(Tv)\mathrm{pre}^-(T_v) for the same sequence without its first entry vv. So pre−(Tv)=pre(Tc1),…,pre(Tck)\mathrm{pre}^-(T_v) = \mathrm{pre}(T_{c_1}), \ldots, \mathrm{pre}(T_{c_k}) for C[v]=[c1,…,ck]C[v] = [c_1, \ldots, c_k]. One step is one run of the body of the loop (lines L4 to L10).

Claim. Suppose that at some moment the stack is S0S_0 followed by the pair (v,0)(v, 0) on top, the last entry of out is vv, and out is XX at this moment. Then after exactly 2∣Tv∣−12|T_v| - 1 more steps, the stack is S0S_0, out is X,pre−(Tv)X, \mathrm{pre}^-(T_v), and during these steps no pair of S0S_0 is read or changed.

Proof. By strong induction on the height of vv. Let C[v]=[c1,…,ck]C[v] = [c_1, \ldots, c_k].

If k=0k = 0, vv is a leaf, TvT_v has one vertex, and pre−(Tv)\mathrm{pre}^-(T_v) is empty. In the next step, line L4 reads (v,0)(v, 0), the test of line L5 fails, and line L10 pops (v,0)(v, 0). That is 1=2⋅1−11 = 2 \cdot 1 - 1 step, and out is still XX.

If k≥1k \ge 1, each child cjc_j has a smaller height than vv, so the claim holds for it. We show by induction on j=0,1,…,kj = 0, 1, \ldots, k: after ∑l≤j2∣Tcl∣\sum_{l \le j} 2|T_{c_l}| steps, the stack is S0,(v,j)S_0, (v, j) and out is X,pre(Tc1),…,pre(Tcj)X, \mathrm{pre}(T_{c_1}), \ldots, \mathrm{pre}(T_{c_j}). For j=0j = 0 this is the start. For j<kj < k, the next step reads (v,j)(v, j), finds j<kj < k at line L5, sets the pair to (v,j+1)(v, j + 1), appends cj+1c_{j+1} to out and pushes (cj+1,0)(c_{j+1}, 0). Now the hypothesis of the claim holds for cj+1c_{j+1}, so after 2∣Tcj+1∣−12|T_{c_{j+1}}| - 1 more steps the stack is S0,(v,j+1)S_0, (v, j + 1) again and out has grown by cj+1,pre−(Tcj+1)=pre(Tcj+1)c_{j+1}, \mathrm{pre}^-(T_{c_{j+1}}) = \mathrm{pre}(T_{c_{j+1}}). The steps used are 1+2∣Tcj+1∣−1=2∣Tcj+1∣1 + 2|T_{c_{j+1}}| - 1 = 2|T_{c_{j+1}}|, and the claim for cj+1c_{j+1} says that the pairs below it, including (v,j+1)(v, j + 1) and S0S_0, are not touched.

At j=kj = k, the stack is S0,(v,k)S_0, (v, k) and out is X,pre−(Tv)X, \mathrm{pre}^-(T_v). The next step finds k=∣C[v]∣k = |C[v]| at line L5 and pops (v,k)(v, k). The total number of steps is ∑l=1k2∣Tcl∣+1=2(∣Tv∣−1)+1=2∣Tv∣−1\sum_{l=1}^{k} 2|T_{c_l}| + 1 = 2(|T_v| - 1) + 1 = 2|T_v| - 1, because the subtrees of the children partition TvT_v minus vv. Only the pair of vv and pairs above it were read or changed. □\square

Theorem. PREORDER(C,r)(C, r) stops after 2n−12n - 1 steps and returns pre(Tr)\mathrm{pre}(T_r), where nn is the number of vertices.

Proof. After lines L1 and L2, the stack is the empty stack S0S_0 followed by (r,0)(r, 0), and out is [r][r]. The claim applies with X=[r]X = [r]. After 2n−12n - 1 steps the stack is empty, so the test of line L3 fails, and out is r,pre−(Tr)=pre(Tr)r, \mathrm{pre}^-(T_r) = \mathrm{pre}(T_r). Line L11 returns it. The count of steps is finite and exact, so the loop terminates. ■\blacksquare

Stack size. By the claim, while the walk is inside TvT_v, the pair of vv stays on the stack, and the pairs on the stack at any moment are the vertices of one path from rr down. So the stack never holds more than h+1h + 1 pairs, where hh is the height of TT.

Back to Preorder traversal