Skip to content

Chapter 33. Tree Traversal

Tree traversal is the process of visiting the vertices of a tree in a specified order.

A tree has no natural linear order. Unlike an array, whose elements are visited from left to right, a tree branches. From a vertex, there may be several children or neighbors to visit next. A traversal rule resolves this choice.

Tree traversal is used to search trees, print their contents, evaluate expressions, copy structures, delete structures, compute summaries, and build auxiliary data. The common traversal families are depth-first traversal and breadth-first traversal. In rooted trees, these appear as preorder, postorder, inorder for binary trees, and level-order traversal.

33.1 Definition

Let

T=(V,E) T=(V,E)

be a tree.

A traversal of TT is an ordered procedure that visits vertices of TT, usually exactly once.

The output of a traversal is a sequence

v1,v2,,vn v_1,v_2,\ldots,v_n

containing the vertices of the tree in the order in which they are visited.

If the tree is rooted, the traversal usually begins at the root. If the tree is unrooted, one often chooses an arbitrary starting vertex and treats the tree as rooted at that vertex for the purpose of traversal.

33.2 Depth-First Traversal

Depth-first traversal explores as far as possible along one branch before returning to visit another branch.

In a rooted tree, this means that after entering a child subtree, the traversal continues inside that subtree before moving to the next sibling subtree. This behavior may be implemented recursively or by using an explicit stack.

Depth-first traversal is natural when the tree itself is recursively defined.

If a rooted tree has root rr and child subtrees

T1,T2,,Tk, T_1,T_2,\ldots,T_k,

then a depth-first traversal processes these subtrees one at a time.

There are two standard depth-first orders for arbitrary rooted trees:

TraversalRule
PreorderVisit the root before its subtrees
PostorderVisit the root after its subtrees

For binary trees, there is also inorder traversal, because each vertex has a left subtree and a right subtree.

33.3 Preorder Traversal

Preorder traversal visits a vertex before visiting its children.

For a rooted tree:

  1. Visit the root.
  2. Traverse each child subtree in order.

If the root has child subtrees

T1,T2,,Tk, T_1,T_2,\ldots,T_k,

then preorder has the form

r, preorder(T1), preorder(T2),,preorder(Tk). r,\ \operatorname{preorder}(T_1),\ \operatorname{preorder}(T_2),\ldots,\operatorname{preorder}(T_k).

For a binary tree with root rr, left subtree LL, and right subtree RR, preorder is

r, L, R. r,\ L,\ R.

This is often called root-left-right order.

Example

Consider the rooted tree:

A(B(D,E),C(F)). A(B(D,E),C(F)).

Here AA is the root. Its children are BB and CC. The children of BB are DD and EE. The child of CC is FF.

The preorder traversal is

A,B,D,E,C,F. A,B,D,E,C,F.

Preorder is useful when a parent must be processed before its descendants. For example, it can be used to copy a tree, serialize a hierarchy, or produce prefix notation from an expression tree.

33.4 Postorder Traversal

Postorder traversal visits a vertex after visiting its children.

For a rooted tree:

  1. Traverse each child subtree in order.
  2. Visit the root.

If the root has child subtrees

T1,T2,,Tk, T_1,T_2,\ldots,T_k,

then postorder has the form

postorder(T1), postorder(T2),,postorder(Tk), r. \operatorname{postorder}(T_1),\ \operatorname{postorder}(T_2),\ldots,\operatorname{postorder}(T_k),\ r.

For a binary tree with root rr, left subtree LL, and right subtree RR, postorder is

L, R, r. L,\ R,\ r.

This is often called left-right-root order.

Example

For the same rooted tree

A(B(D,E),C(F)), A(B(D,E),C(F)),

the postorder traversal is

D,E,B,F,C,A. D,E,B,F,C,A.

Postorder is useful when a vertex depends on information from its descendants. It is used for deleting trees, computing subtree sizes, evaluating expression trees, and dynamic programming on trees.

33.5 Inorder Traversal

Inorder traversal is primarily defined for binary trees.

For a binary tree with root rr, left subtree LL, and right subtree RR, inorder traversal is

L, r, R. L,\ r,\ R.

That is:

  1. Traverse the left subtree.
  2. Visit the root.
  3. Traverse the right subtree.

Example

Consider the binary tree

A(B(D,E),C(,F)). A(B(D,E),C(\varnothing,F)).

The inorder traversal is

D,B,E,A,C,F. D,B,E,A,C,F.

Inorder traversal is especially important for binary search trees. If each node key is greater than every key in its left subtree and less than every key in its right subtree, then inorder traversal visits the keys in ascending order.

33.6 Level-Order Traversal

Level-order traversal visits vertices by increasing depth.

It begins at the root, then visits all vertices at depth 11, then all vertices at depth 22, and so on.

This is the tree version of breadth-first search. It is commonly implemented with a queue.

For the rooted tree

A(B(D,E),C(F)), A(B(D,E),C(F)),

the levels are:

LevelVertices
00AA
11B,CB,C
22D,E,FD,E,F

Thus the level-order traversal is

A,B,C,D,E,F. A,B,C,D,E,F.

Level-order traversal is useful when the distance from the root matters. It appears in shortest-path trees, breadth-first search trees, heap storage, and layer-by-layer processing.

33.7 Recursive Traversal

Recursive traversal uses the recursive definition of a rooted tree.

For preorder:

Preorder(T): \operatorname{Preorder}(T):
  1. If TT is empty, stop.
  2. Visit the root.
  3. Apply preorder to each child subtree.

For postorder:

Postorder(T): \operatorname{Postorder}(T):
  1. If TT is empty, stop.
  2. Apply postorder to each child subtree.
  3. Visit the root.

For binary inorder:

Inorder(T): \operatorname{Inorder}(T):
  1. If TT is empty, stop.
  2. Apply inorder to the left subtree.
  3. Visit the root.
  4. Apply inorder to the right subtree.

The recursion ends at leaves. A leaf has no child subtrees, so it is visited directly.

33.8 Stack-Based Traversal

Depth-first traversal can also be implemented with an explicit stack.

A stack is a last-in, first-out structure. It records vertices whose remaining work has been deferred.

For preorder traversal of an ordered rooted tree:

  1. Push the root on the stack.
  2. While the stack is nonempty:
    • Pop a vertex.
    • Visit it.
    • Push its children in reverse order.

The reverse push order ensures that the leftmost or first child is processed first.

For binary trees, preorder can be written as:

preorder(root):
    if root is null:
        return

    stack = empty stack
    push root onto stack

    while stack is not empty:
        v = pop stack
        visit v

        if right(v) is not null:
            push right(v)

        if left(v) is not null:
            push left(v)

The stack version avoids recursive calls. It is useful when recursion depth may be large.

33.9 Queue-Based Traversal

Breadth-first traversal uses a queue.

A queue is a first-in, first-out structure. It stores vertices in the order in which they were discovered.

For level-order traversal:

level_order(root):
    if root is null:
        return

    queue = empty queue
    enqueue root

    while queue is not empty:
        v = dequeue queue
        visit v

        for each child c of v, in order:
            enqueue c

This algorithm visits vertices in increasing depth. All vertices at depth dd are processed before any vertex at depth d+1d+1.

33.10 Traversal and Running Time

Every standard traversal visits each vertex once.

If the tree has

n n

vertices, then preorder, postorder, inorder, and level-order traversal all run in

O(n) O(n)

time.

The auxiliary memory depends on the traversal and the tree shape.

TraversalAuxiliary structureTypical extra space
Recursive DFSCall stackO(h)O(h)
Iterative DFSExplicit stackO(h)O(h) to O(n)O(n)
BFSQueueO(w)O(w)

Here hh is the height of the tree, and ww is the maximum number of vertices on any level.

In a balanced binary tree,

h=O(logn). h = O(\log n).

In a path-like tree,

h=O(n). h = O(n).

For breadth-first traversal, the queue may become large when the tree is wide.

33.11 Traversal of Binary Search Trees

Traversal order has special meaning in binary search trees.

Let TT be a binary search tree. For every vertex with key kk, all keys in the left subtree are less than kk, and all keys in the right subtree are greater than kk.

Then inorder traversal returns the keys in ascending order.

Theorem 33.1

The inorder traversal of a binary search tree lists its keys in increasing order.

Proof

We prove the statement by induction on the number of vertices.

If the tree is empty or has one vertex, the result is immediate.

Let the root have key kk. By the binary search tree property, every key in the left subtree is less than kk, and every key in the right subtree is greater than kk.

By the induction hypothesis, inorder traversal lists the left subtree in increasing order and the right subtree in increasing order.

Inorder traversal visits:

left subtree,k,right subtree. \text{left subtree},\quad k,\quad \text{right subtree}.

Therefore all listed keys appear in increasing order.

33.12 Traversal and Expression Trees

Expression trees use leaves for operands and internal vertices for operators.

For a binary expression tree:

TraversalNotation produced
PreorderPrefix notation
InorderInfix notation
PostorderPostfix notation

For example, consider the expression tree for

(a+b)(cd). (a+b)(c-d).

Its root is multiplication. The left subtree is addition, and the right subtree is subtraction.

Preorder gives

$$

  • \ +\ a\ b\ -\ c\ d. $$

Inorder gives

(a+b)(cd). (a+b)*(c-d).

Postorder gives

a b + c d  . a\ b\ +\ c\ d\ -\ *.

Postorder is useful for evaluation because each operator is visited after its operands.

33.13 Computing Subtree Quantities

Postorder traversal is the standard method for computing quantities that depend on children.

For example, the size of the subtree rooted at vv is

size(v)=1+csize(c), \operatorname{size}(v) = 1+\sum_{c}\operatorname{size}(c),

where the sum is over all children cc of vv.

To compute this value, one must first compute the size of each child subtree. Therefore the natural traversal is postorder.

Similarly, postorder is used for:

QuantityRecurrence
Height1+maxcheight(c)1+\max_c \operatorname{height}(c)
Subtree size1+csize(c)1+\sum_c \operatorname{size}(c)
Leaf countSum of leaf counts of children
Dynamic programming valueFunction of child values

The common pattern is that the value at a vertex is computed after the values of its children are known.

33.14 Traversal and Search

Traversal can be used to search for a vertex satisfying a condition.

For example, one may search for a key, a label, a minimum value, or a vertex with a certain property.

A generic depth-first search on a rooted tree has the form:

search(v):
    if v satisfies the condition:
        return v

    for each child c of v:
        result = search(c)
        if result is not null:
            return result

    return null

This is preorder search. It tests a vertex before searching below it.

Breadth-first search instead tests vertices level by level. It finds a satisfying vertex of minimum depth if one exists.

33.15 Traversal Orders and Reconstruction

Traversal sequences can sometimes determine a tree.

For binary trees with distinct labels:

Given traversalsDetermines tree?
Preorder and inorderYes
Postorder and inorderYes
Preorder and postorderNot always
Level-order and inorderYes

Inorder provides the division between left and right subtrees. Preorder identifies the root first. Postorder identifies the root last. Together with inorder, either is enough to reconstruct the tree.

Without inorder, the left-right division may remain ambiguous.

33.16 Traversal in General Trees

For a general rooted tree, a vertex may have any number of children.

Preorder and postorder remain natural:

preorder(v):v, T1,,Tk. \operatorname{preorder}(v): \quad v,\ T_1,\ldots,T_k. postorder(v):T1,,Tk, v. \operatorname{postorder}(v): \quad T_1,\ldots,T_k,\ v.

Inorder has no single standard definition for general rooted trees, because there is no distinguished position between exactly two subtrees. Some conventions place the root after the first child subtree, but this is less universal than binary-tree inorder.

Thus inorder is best regarded as a binary-tree traversal.

33.17 Traversal in Algorithms

Tree traversal is a basic component inside larger algorithms.

Algorithmic taskCommon traversal
Copy a treePreorder
Delete a treePostorder
Evaluate expression treePostorder
Print binary search tree in sorted orderInorder
Compute tree heightPostorder
Find shallowest targetLevel order
Serialize hierarchyPreorder or level order
Dynamic programming on treesPostorder

The traversal is chosen according to dependency. If a parent must be seen first, use preorder. If children must be computed first, use postorder. If depth matters, use level order.

33.18 Summary

Tree traversal converts a branching structure into an ordered sequence of vertex visits.

Depth-first traversal explores one branch before moving to another. Its main rooted forms are preorder and postorder. In binary trees, inorder traversal is also fundamental.

Breadth-first traversal visits vertices level by level and is implemented with a queue.

Each standard traversal visits all vertices in linear time. The appropriate traversal depends on the task: preorder for parent-first work, postorder for child-first computation, inorder for sorted output in binary search trees, and level order for depth-based processing.