📖 Scenario: You are working with a simple family tree where each person can have up to two children. You want to visit all family members in a special order: first the left child, then the right child, and finally the parent. This order is called postorder traversal.
🎯 Goal: Build a Rust program that creates a small tree of family members and prints their names in postorder (left, right, root) order.
📋 What You'll Learn
Create a binary tree node struct called Node with a name field and optional left and right children.
Create a tree with exactly three nodes: root named "Grandparent", left child named "Parent", and right child named "Uncle".
Write a recursive function called postorder_traversal that visits nodes in left, right, root order and collects their names.
Print the names collected by postorder_traversal separated by arrows (->).
💡 Why This Matters
🌍 Real World
Tree traversal is used in many real-world applications like file system navigation, expression evaluation, and organizing hierarchical data.
💼 Career
Understanding tree traversal is essential for software developers working with data structures, algorithms, and systems that manage hierarchical information.
Progress0 / 4 steps
1
Create the tree nodes
Create a struct called Node with a name field of type String, and two optional children fields called left and right of type Option>. Then create three nodes: grandparent with name "Grandparent", parent with name "Parent", and uncle with name "Uncle". Set parent and uncle as children of grandparent.
DSA Rust
Hint
Use Option> for children to allow empty or present child nodes. Use String::from to create names.
2
Create a vector to collect names
Inside main, create a mutable vector called names of type Vec to store the names of nodes visited during traversal.
DSA Rust
Hint
Use let mut names: Vec = Vec::new(); to create an empty vector that can change.
3
Write the postorder traversal function
Write a recursive function called postorder_traversal that takes a reference to a Node and a mutable reference to a Vec. It should visit the left child first, then the right child, and finally add the current node's name to the vector.
DSA Rust
Hint
Use if let Some(child) = &node.left to check and recurse on children. Add the current node's name after visiting children.
4
Print the postorder traversal result
Print the contents of the names vector joined by " -> " to show the postorder traversal sequence.
DSA Rust
Hint
Use println!("{}", names.join(" -> ")); to print the vector elements joined by arrows.
Practice
(1/5)
1. What is the order of nodes visited in a postorder traversal of a binary tree?
easy
A. Left subtree, Right subtree, Root node
B. Root node, Left subtree, Right subtree
C. Root node, Right subtree, Left subtree
D. Right subtree, Left subtree, Root node
Solution
Step 1: Understand postorder traversal definition
Postorder traversal visits nodes in the order: left subtree first, then right subtree, and finally the root node.
Step 2: Match the order with options
Left subtree, Right subtree, Root node matches this order exactly: Left subtree, Right subtree, Root node.
Final Answer:
Left subtree, Right subtree, Root node -> Option A
Quick Check:
Postorder = Left, Right, Root [OK]
Hint: Remember postorder ends with root after children [OK]
Common Mistakes:
Confusing postorder with preorder or inorder
Visiting root before children
Swapping left and right subtree order
2. Which of the following Rust function signatures correctly represents a recursive postorder traversal function for a binary tree node defined as struct Node { left: Option, right: Option, value: i32 }?
The tree root is 1, left child 2, right child 3. Postorder visits left (2), right (3), then root (1).
Step 2: Confirm printed order
Values printed in order: 2, then 3, then 1, matching 2 3 1 .
Final Answer:
2 3 1 -> Option D
Quick Check:
Postorder prints left, right, root = 2 3 1 [OK]
Hint: Print order matches left-right-root traversal [OK]
Common Mistakes:
Confusing preorder or inorder output
Missing spaces in print output
Ignoring None children
4. The following Rust code attempts a postorder traversal but has a bug. What is the error?
fn postorder(node: &Option) {
if let Some(n) = node {
print!("{} ", n.value);
postorder(&n.left);
postorder(&n.right);
}
}
medium
A. It causes a stack overflow due to infinite recursion
B. It prints root before children, not postorder
C. It does not handle None nodes correctly
D. It borrows node mutably but parameter is immutable
Solution
Step 1: Analyze print statement position
The print happens before recursive calls to left and right children, so root is printed first.
Step 2: Compare with postorder definition
Postorder requires visiting left and right children before root, so this order is incorrect.
Final Answer:
It prints root before children, not postorder -> Option B
Quick Check:
Print after children for postorder [OK]
Hint: Print root after children for correct postorder [OK]
Common Mistakes:
Printing root before recursive calls
Confusing preorder with postorder
Ignoring None checks
5. You want to collect all node values of a binary tree in postorder traversal into a vector in Rust. Which of the following code snippets correctly implements this?
hard
A. fn postorder_collect(node: &Option) -> Vec<i32> {
let mut vals = Vec::new();
if let Some(n) = node {
vals.push(n.value);
vals.extend(postorder_collect(&n.left));
vals.extend(postorder_collect(&n.right));
}
vals
}
B. fn postorder_collect(node: &Option, vals: &mut Vec<i32>) {
if let Some(n) = node {
vals.push(n.value);
postorder_collect(&n.left, vals);
postorder_collect(&n.right, vals);
}
}
C. fn postorder_collect(node: &Option) -> Vec<i32> {
let mut vals = Vec::new();
if let Some(n) = node {
vals.extend(postorder_collect(&n.left));
vals.extend(postorder_collect(&n.right));
vals.push(n.value);
}
vals
}
D. fn postorder_collect(node: &Option, vals: &mut Vec<i32>) {
if let Some(n) = node {
postorder_collect(&n.right, vals);
postorder_collect(&n.left, vals);
vals.push(n.value);
}
}
Solution
Step 1: Understand postorder collection logic
Postorder means collect left subtree values, then right subtree values, then root value.
Step 2: Check each code snippet for correct order and return type
fn postorder_collect(node: &Option) -> Vec<i32> {
let mut vals = Vec::new();
if let Some(n) = node {
vals.extend(postorder_collect(&n.left));
vals.extend(postorder_collect(&n.right));
vals.push(n.value);
}
vals
} correctly collects left and right subtree vectors first, then pushes root value, returning the combined vector.
Final Answer:
fn postorder_collect(node: &Option) -> Vec<i32> { let mut vals = Vec::new(); if let Some(n) = node { vals.extend(postorder_collect(&n.left)); vals.extend(postorder_collect(&n.right)); vals.push(n.value); } vals } -> Option C
Quick Check:
Collect left, right, then root in vector [OK]
Hint: Collect children first, then push root value [OK]
Common Mistakes:
Pushing root before children
Not returning combined vector
Using mutable vector incorrectly
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.