Rooted Trees, Traversals, and Structural Recursion
What This Concept Is
A rooted tree is a tree with one distinguished vertex called the root. Once rooted, the tree gains directional language:
- parent -- for a nonroot vertex, its unique neighbor toward the root; the root has no parent.
- child -- a vertex one step further from the root.
- ancestor / descendant -- transitive parent / child.
- subtree -- the tree rooted at a descendant (including itself and everything below).
- leaf -- a vertex with no children.
- internal (non-leaf) vertex -- at least one child.
- depth of $v$ -- edges on the path from root to $v$. The root has depth $0$.
- height of the tree -- maximum depth over all vertices; equivalently, the length of the longest root-to-leaf path.
Traversal orders are systematic schemes for visiting every vertex of a rooted tree exactly once, each suited to different recursive computations:
- preorder: visit the root, then traverse each child's subtree in preorder. Produces: root, left subtree, right subtree (for a binary tree). Natural for serializing a tree or for top-down accumulation (e.g., propagating a depth counter).
- postorder: traverse each child's subtree in postorder, then visit the root. Produces: left subtree, right subtree, root. Natural for bottom-up aggregation -- computing a value at each node that depends on child results first (e.g., subtree size, directory size, expression evaluation, deletion).
- inorder (binary trees only): left subtree, root, right subtree. For a BST, inorder yields the keys in sorted order.
- level-order (BFS): visit by increasing depth. Natural for level-by-level processing and for shortest-path trees.
Traversals are not just algorithmic conveniences; they encode the dependency discipline a computation requires. Postorder encodes "children-before-parent" data flow; preorder encodes "parent-before-children"; level-order encodes "distance-layer-by-layer."
Why It Matters Here
Rooted trees connect graph structure to recursive computation. Many algorithms and data structures are naturally described by subtrees, recursive descent, or traversal order.
This is also where tree structure stops being purely static and becomes procedural -- you can think of a traversal as "walking the recursion." Dynamic programming on trees (subtree DP) is exactly postorder traversal: combine child answers into a parent answer. Parsing a language generates a preorder traversal of the parse tree. Every standard tree data structure uses one or more of these traversals for its core operations.
Downstream, recursive descent parsers (compilers, Semester 3), segment/Fenwick trees (Semester 2), DOM traversal in browsers, and file-system find all use traversal semantics deliberately.
Concrete Examples
Example 1: postorder for subtree sum. Let a rooted tree have an integer weight at each vertex. Compute, at every vertex, the sum of weights in its subtree.
Recursive definition: $\mathrm{sum}(v) = w(v) + \sum_{c \in \mathrm{children}(v)} \mathrm{sum}(c)$.
Pseudocode (postorder):
function subtreeSum(v):
total = w(v)
for each child c of v:
total += subtreeSum(c)
store total at v
return total
The key point: total cannot be finalized at v until every child's total is known. That dependency is postorder. If you tried preorder, you would be asking for child results before computing them -- impossible without two passes.
Example 2: inorder traversal of a BST yields sorted output. In a binary search tree (BST), the invariant is that for every node $v$, all keys in $v$'s left subtree are less than $v$'s key, and all keys in $v$'s right subtree are greater. An inorder traversal visits left-subtree, root, right-subtree; by induction on subtree size, this produces keys in ascending order.
This is why inorder is the "natural" traversal for BSTs -- it exposes the ordering the data structure was designed to maintain. Preorder does not generally guarantee sorted output.
Example 3: preorder for serializing a tree. To serialize a rooted tree as a string for storage or transmission, use preorder with explicit null markers:
serialize(v):
if v is null: emit "#"
else: emit v.value; serialize(v.left); serialize(v.right)
With unambiguous token boundaries and a null marker distinct from payloads, the serialized string uniquely determines the tree and is reconstructed by a corresponding preorder deserialization. Postorder would work too, but preorder is especially clean because the root is immediately visible at the start of each subtree's encoding.
Common Confusion / Misconceptions
- The root is mathematically forced. No -- the root is chosen for the purpose of the problem. Any vertex of an unrooted tree can be made the root; different choices give different parent/child relationships but the same underlying graph.
- Tree depth = vertex degree. No. Depth is a per-vertex distance from the root; degree is the number of incident edges. A tree can be deep but low-degree (a path, $P_n$) or shallow but high-degree (a star, $K_{1,n-1}$).
- Traversal = graph structure. Traversal is an algorithmic lens on a tree. The same tree supports many traversals; the graph doesn't change, only the visitation order.
- Inorder generalizes beyond binary trees. No -- inorder requires an ordering between children (left/right), which is only well-defined in binary (or more generally $k$-ary ordered) trees. For general rooted trees, pre/post/level-order are the standard three.
How To Use It
When a question involves hierarchical decomposition, recursive processing, or parent-child dependency, root the tree and work by subtrees.
Ask:
- does the computation flow top-down (root to leaves, parent informs children)? $\to$ preorder.
- does it flow bottom-up (leaves to root, children inform parent)? $\to$ postorder.
- does it process one depth level at a time? $\to$ level-order / BFS.
- is the tree a binary search tree and I want sorted output? $\to$ inorder.
- am I serializing/deserializing? $\to$ preorder with null markers is the cleanest.
- do I need both directions (e.g., propagate up then down)? $\to$ two-pass: postorder then preorder.
- what is the recursion's base case -- leaves or null subtrees?
Rooting choice matters for convenience. For a tree with no natural root (e.g., a communication network), choose a root that minimizes maximum depth (a center vertex) or that is algorithmically convenient (e.g., the first-inserted vertex).
Transfer to the workshop model
Use this concept to justify or challenge one result in the workshop project. Specify the counted objects or graph semantics before interpreting any numerical output.
Check Yourself
- Why does rooting add useful structure without changing the underlying graph? What is gained, and what is preserved?
- Which traversal is natural for bottom-up computation? Why?
- What is a subtree, precisely? Is the subtree rooted at a leaf the leaf itself?
- For a BST, why does inorder produce sorted output? Prove by induction on subtree size.
- Can a tree have a traversal that is neither pre-, in-, post-, nor level-order? If yes, give a simple example.
- What is the relationship between DFS on a graph and preorder on the resulting DFS tree?
Mini Drill or Application
Draw a rooted tree with at least $7$ vertices and do all of these:
- label parent and child relations for every non-root vertex.
- list preorder, inorder (if binary), postorder, and level-order traversals.
- identify a recursive computation that would naturally use postorder (e.g., subtree size, count of leaves, maximum weight).
- identify a recursive computation that would naturally use preorder (e.g., depth of each node, labeling each vertex with its root-to-vertex path).
- serialize your tree as a preorder string with
#null markers and deserialize it on paper to check round-tripping.
Read This Only If Stuck
Use the bounded reading guide to locate the topic in MCS or Rosen. These links open indexes. Check the actual heading in your edition, read one targeted explanation, then reconstruct the argument with the book closed.
Root choice, child order and serialization are extra data
A root has no parent. A nonroot parent is its neighbor on the unique path to the root. Rooted leaves have no children, so the singleton root is a leaf and the degree-one root of a two-vertex tree is not. An unrooted graph leaf convention typically uses degree one instead.
Preorder and postorder need a specified child order to give a unique sequence. Binary-tree serialization also needs unambiguous token boundaries and a null marker distinct from every payload. Concatenating unescaped values is not a uniquely decodable format merely because traversal is preorder. Transfer: give two roots and two child orders for one tree, and identify which invariants remain.
After your attempt use practice feedback and model contracts to check the argument.