name: Binary Tree Traversal slug: tree-traversal difficulty_level: 2 description: > Visit all nodes in a binary tree in specific orders: preorder (root-left-right), inorder (left-root-right), postorder (left-right-root), or level-order (BFS). Each order reveals different structural information about the tree. when_to_use: | - Serializing/deserializing trees - Validating BST properties (inorder gives sorted order) - Computing tree properties (height, size, sum) - Copying or comparing trees - Path sum and path finding problems metaphor: | Imagine reading a family tree. **Preorder** is like announcing yourself first, then introducing your children. **Inorder** is alphabetical—left child, then you, then right child. **Postorder** is like calculating taxes—you need to know your children's totals before computing your own. Another way to think about it: **preorder** is top-down (decisions flow from root to leaves), **postorder** is bottom-up (results bubble from leaves to root). core_concept: | The three traversal orders differ only in *when* you process the current node relative to its children: - **Preorder**: Process **before** children → good for copying trees, prefix expressions - **Inorder**: Process **between** children → BST gives sorted order - **Postorder**: Process **after** children → good for deletion, evaluating expressions The key insight is that these traversals naturally map to different problems: - Need to see parents before children? → **Preorder** - Need to aggregate child results? → **Postorder** - Need sorted BST elements? → **Inorder** - Need level-by-level? → **BFS** visualization: | **Example tree:** ``` 1 / \ 2 3 / \ 4 5 ``` **Preorder (Root → Left → Right):** ``` Visit 1 → Visit 2 → Visit 4 → Visit 5 → Visit 3 Result: [1, 2, 4, 5, 3] ``` **Inorder (Left → Root → Right):** ``` Visit 4 → Visit 2 → Visit 5 → Visit 1 → Visit 3 Result: [4, 2, 5, 1, 3] For BST: gives elements in sorted order! ``` **Postorder (Left → Right → Root):** ``` Visit 4 → Visit 5 → Visit 2 → Visit 3 → Visit 1 Result: [4, 5, 2, 3, 1] Children processed before parent—useful for computing heights/sizes. ``` **Level-order (BFS):** ``` Level 0: [1] Level 1: [2, 3] Level 2: [4, 5] Result: [1, 2, 3, 4, 5] ``` code_template: | from collections import deque class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def preorder_recursive(root: TreeNode) -> list: """Preorder: Root → Left → Right""" if not root: return [] return ([root.val] + preorder_recursive(root.left) + preorder_recursive(root.right)) def preorder_iterative(root: TreeNode) -> list: """Iterative preorder using stack.""" if not root: return [] result = [] stack = [root] while stack: node = stack.pop() result.append(node.val) # Push right first so left is processed first if node.right: stack.append(node.right) if node.left: stack.append(node.left) return result def inorder_recursive(root: TreeNode) -> list: """Inorder: Left → Root → Right""" if not root: return [] return (inorder_recursive(root.left) + [root.val] + inorder_recursive(root.right)) def inorder_iterative(root: TreeNode) -> list: """Iterative inorder using stack.""" result = [] stack = [] current = root while current or stack: # Go left as far as possible while current: stack.append(current) current = current.left # Process current node current = stack.pop() result.append(current.val) # Move to right subtree current = current.right return result def postorder_recursive(root: TreeNode) -> list: """Postorder: Left → Right → Root""" if not root: return [] return (postorder_recursive(root.left) + postorder_recursive(root.right) + [root.val]) def postorder_iterative(root: TreeNode) -> list: """Iterative postorder using two stacks.""" if not root: return [] result = [] stack = [root] while stack: node = stack.pop() result.append(node.val) if node.left: stack.append(node.left) if node.right: stack.append(node.right) return result[::-1] # Reverse for postorder def level_order(root: TreeNode) -> list[list]: """Level-order traversal using BFS.""" if not root: return [] result = [] queue = deque([root]) while queue: level = [] for _ in range(len(queue)): node = queue.popleft() level.append(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) result.append(level) return result recognition_signals: - "binary tree" - "tree traversal" - "preorder" - "inorder" - "postorder" - "level order" - "serialize tree" - "flatten tree" - "BST to sorted" - "kth smallest in BST" - "validate BST" - "path sum" common_mistakes: - title: Stack order in iterative preorder description: | Pushing left child before right child processes right first because stacks are LIFO. fix: | Push right child first, then left child: ```python if node.right: stack.append(node.right) # Push right first if node.left: stack.append(node.left) # Left popped first ``` - title: Iterative inorder is tricky description: | The iterative inorder traversal is harder to get right than preorder or postorder because you need to track when to go left vs when to process. fix: | Use the "go left until null, then process and go right" pattern: ```python while current or stack: while current: stack.append(current) current = current.left current = stack.pop() process(current) current = current.right ``` - title: Forgetting null checks description: | Accessing `node.left` or `node.right` without checking if node is None causes attribute errors. fix: | Always check for null nodes first: ```python if not root: return [] ``` - title: Modifying tree during traversal description: | Changing node values or structure while traversing can cause missed nodes or infinite loops. fix: | Collect nodes to modify in a separate pass, or use a traversal that processes children before modifying the parent. variations: - name: Morris Traversal description: | Inorder traversal using O(1) space by temporarily modifying the tree (threading right pointers to inorder successors). example: "Recover Binary Search Tree, Inorder without stack" - name: Boundary Traversal description: | Traverse only the boundary of the tree: left boundary, leaves, right boundary in reverse. example: "Boundary of Binary Tree" - name: Vertical Order Traversal description: | Group nodes by their horizontal distance from root. Nodes at same horizontal distance are in the same vertical line. example: "Vertical Order Traversal, Binary Tree Right Side View" - name: Zigzag Level Order description: | Level-order but alternating direction: left-to-right, then right-to-left, and so on. example: "Binary Tree Zigzag Level Order Traversal" - name: Tree Serialization description: | Use traversal order to convert tree to string and back. Preorder with null markers is common. example: "Serialize and Deserialize Binary Tree" related_patterns: - dfs - bfs prerequisite_patterns: []