This lesson on Binary Trees & Traversals is hands-on and example-driven. You will master the mechanics of traversing binary trees using both Depth-First Search (DFS) and Breadth-First Search (BFS). You will be able to systematically compute Pre-order, In-order, and Post-order sequences for any binary tree structure and apply recursive traversal rules under interview conditions.
What You'll Be Able To Do
- Categorize binary tree traversal algorithms into depth-first and breadth-first strategies.
- Derive the In-order (Left-Root-Right) traversal sequence for simple and nested binary trees.
- Compute the Pre-order (Root-Left-Right) sequence by processing root nodes prior to subtree recursion.
- Generate the Post-order (Left-Right-Root) sequence by resolving all child subtrees before parent nodes.
- Execute Breadth-First Search (Level Order) to sequence tree nodes horizontally level by level.
Detailed Concept Walkthrough
1. DFS Traversal Fundamentals and Naming Mnemonic
Depth-First Search (DFS) explores as deep as possible along each branch before backtracking. The three DFS variants differ strictly by when the root node is visited relative to its left and right subtrees.
- Mechanism: In every DFS variant, the Left subtree is always visited before the Right subtree; only the placement of the Root node changes.
- Naming Mnemonic: The prefix indicates the Root position: 'Pre' visits Root before children, 'In' visits Root in between children, and 'Post' visits Root after children.
- Under the Hood: Recursive implementations utilize the call stack to maintain parent context while descending to leaf nodes, unwinding frames automatically upon reaching base cases.
# Node structure for binary tree traversals
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
Key Takeaway: The prefix (Pre, In, Post) explicitly defines where the root node is evaluated relative to its subtrees.
2. Pre-order Traversal (Root-Left-Right)
Pre-order traversal processes the current node immediately upon discovery before recursively traversing its left and right subtrees.
- Execution Flow: The algorithm processes the current root, makes a recursive call to the left child, and finally makes a recursive call to the right child.
- Under the Hood: Because the parent node is evaluated first, this pattern is useful for cloning trees or serializing hierarchical structures from top to bottom.
- Best Practice: Ensure the base case explicitly checks for
Noneor null nodes to prevent unnecessary call stack depth and attribute errors.
def preorder_traversal(root):
# Base case: empty subtree
if not root:
return []
# Process: Root -> Left -> Right
return [root.val] + preorder_traversal(root.left) + preorder_traversal(root.right)
Key Takeaway: Pre-order visits parent nodes first, making it ideal for prefix notation and top-down tree reconstruction.
3. In-order Traversal (Left-Root-Right)
In-order traversal completely processes the entire left subtree, evaluates the current root, and then processes the right subtree.
- Execution Flow: Execution dives down the leftmost path until reaching a leaf's null pointer, evaluates the leaf, and then checks the right child.
- Under the Hood: For a Binary Search Tree (BST), In-order traversal visits all node values in strictly non-decreasing sorted order.
- Recursive Nuance: Internal nodes act as temporary roots; they cannot be processed until their entire left sub-hierarchy resolves completely.
def inorder_traversal(root):
# Base case: empty subtree
if not root:
return []
# Process: Left -> Root -> Right
return inorder_traversal(root.left) + [root.val] + inorder_traversal(root.right)
Key Takeaway: In-order traversal always produces sorted output when applied to a Binary Search Tree.
4. Post-order Traversal (Left-Right-Root)
Post-order traversal processes both left and right subtrees completely before evaluating the parent root node.
- Execution Flow: Recursion reaches the bottom-most leaves first, resolves sibling subtrees, and finally visits the common parent node on the return path.
- Under the Hood: Because child dependencies are fully evaluated prior to the parent, this pattern is essential for bottom-up operations like node deletion or subtree height calculation.
- Best Practice: Treat every node systematically as its own sub-root to avoid prematurely processing a parent before both branches return.
def postorder_traversal(root):
# Base case: empty subtree
if not root:
return []
# Process: Left -> Right -> Root
return postorder_traversal(root.left) + postorder_traversal(root.right) + [root.val]
Key Takeaway: Post-order processes bottom-up, ensuring all child dependencies are resolved before the parent.
5. Breadth-First Search (BFS) / Level Order Traversal
Breadth-First Search traverses tree nodes horizontally level by level from top to bottom and left to right.
- Mechanism: Unlike DFS which dives vertically into branch depth, BFS consumes nodes across the entire current horizontal tier before advancing to the next depth.
- Under the Hood: BFS is iteratively implemented using a First-In, First-Out (FIFO) queue rather than the recursive call stack.
- Execution Flow: Dequeue the front node, record its value, and enqueue its left and right children if they exist.
from collections import deque
def level_order_traversal(root):
if not root:
return []
result, queue = [], deque([root])
while queue:
node = queue.popleft()
result.append(node.val)
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
return result
Key Takeaway: BFS scans nodes horizontally level by level using a FIFO queue rather than call stack recursion.
Topics Covered in Binary Trees & Traversals
- Tree Traversal Overview (0:47 - 1:05) — The instructor introduces tree traversals and categorizes them into depth-first and breadth-first techniques.
- Introduction to DFS (1:05 - 1:18) — DFS mechanics are explained along with its three main variants: In-order, Pre-order, and Post-order.
- In-order Traversal Rule (1:21 - 2:20) — The Left-Root-Right recursive rule is demonstrated on a simple binary tree.
- Pre-order Traversal Rule (2:22 - 3:02) — The Root-Left-Right sequence is calculated and verified for the sample tree.
- Post-order Traversal Rule (3:02 - 3:32) — The Left-Right-Root sequence is applied to complete the baseline DFS demonstrations.
- DFS Naming Mnemonic (3:32 - 3:45) — A mnemonic is presented showing how prefix names correspond directly to root processing order.
- Complex Tree Application (3:46 - 5:52) — The three DFS traversal algorithms are applied systematically across a larger, multi-level tree hierarchy.
- BFS Level Order Traversal (6:17 - 6:54) — Breadth-First Search is defined and contrasted with DFS as a horizontal, level-by-level processing method.
DSA for Interviews Cheat Sheet
-
Pre-order Traversal— Visits Root, Left subtree, then Right subtree recursivelyresult = [root.val] + pre(root.left) + pre(root.right) -
In-order Traversal— Visits Left subtree, Root, then Right subtree recursivelyresult = in_ord(root.left) + [root.val] + in_ord(root.right) -
Post-order Traversal— Visits Left subtree, Right subtree, then Root recursivelyresult = post(root.left) + post(root.right) + [root.val] -
Level-order Traversal— Visits all tree nodes level by level using a queuequeue.append(root); node = queue.popleft()
Comparison Table
| Traversal Type | Evaluation Order | Primary Direction |
|---|---|---|
| Pre-order | Root -> Left -> Right | Vertical depth-first down branches |
| In-order | Left -> Root -> Right | Vertical depth-first down branches |
| Post-order | Left -> Right -> Root | Vertical depth-first bottom-up |
| Level-order | Level by level (L to R) | Horizontal breadth-first across tiers |
Common Pitfalls
- Mistake: Treating subtrees as flat nodes instead of applying rules recursively. Avoid: Apply the traversal rule to every child node as its own root.
- Mistake: Confusing the relative position of the root node across DFS variants. Avoid: Use the naming mnemonic where Pre/In/Post defines root placement relative to children.
- Mistake: Mixing up BFS level order with DFS vertical exploration during manual tree tracing. Avoid: Process nodes horizontally row-by-row for BFS, and down full branches for DFS.
FAQs
- How can I easily remember the difference between Pre-order, In-order, and Post-order? Look at the prefix: 'Pre' puts the root first (Root-L-R), 'In' puts the root in the middle (L-Root-R), and 'Post' puts the root last (L-R-Root). Left always precedes Right.
- Does the left child always come before the right child in standard DFS? Yes, standard tree traversals evaluate the left subtree before the right subtree across Pre-order, In-order, and Post-order.
- Why does In-order traversal output sorted elements on a Binary Search Tree (BST)? A BST guarantees that all left descendants are smaller and right descendants are larger, so visiting Left then Root then Right naturally orders the values.
- What data structure differentiates BFS from DFS under the hood? DFS utilizes a Last-In, First-Out (LIFO) call stack, whereas BFS utilizes a First-In, First-Out (FIFO) queue.