BST Traversal
BST Traversal
Category
Binary Search Trees (BST)
Difficulty
Medium
Problem Statement
Given a Binary Search Tree (BST), implement three classic depth-first traversal methods: in-order, pre-order, and post-order. Each traversal visits every node exactly once but in a different order, and the result is an array of node values in the order they were visited.
- In-order: left subtree, current node, right subtree
- Pre-order: current node, left subtree, right subtree
- Post-order: left subtree, right subtree, current node
Intuition
Each traversal order captures a different structural perspective of the tree. In-order traversal on a BST produces values in sorted (ascending) order because the BST property guarantees that all left descendants are smaller and all right descendants are larger. Pre-order traversal captures the structure needed to reconstruct the tree (root first, then children). Post-order traversal processes children before parents, which is useful for deletion or bottom-up computations.
The recursive nature of trees maps directly to recursive function calls: at each node, you choose when to "visit" the current node relative to recursing on its children.
Approach
- Start at the root node.
- For in-order traversal:
- Recursively traverse the left subtree.
- Append the current node's value to the result array.
- Recursively traverse the right subtree.
- For pre-order traversal:
- Append the current node's value to the result array.
- Recursively traverse the left subtree.
- Recursively traverse the right subtree.
- For post-order traversal:
- Recursively traverse the left subtree.
- Recursively traverse the right subtree.
- Append the current node's value to the result array.
- Base case: if the current node is null, return immediately.
Pseudocode
function inOrderTraverse(node, array):
if node is null:
return
inOrderTraverse(node.left, array)
array.append(node.value)
inOrderTraverse(node.right, array)
function preOrderTraverse(node, array):
if node is null:
return
array.append(node.value)
preOrderTraverse(node.left, array)
preOrderTraverse(node.right, array)
function postOrderTraverse(node, array):
if node is null:
return
postOrderTraverse(node.left, array)
postOrderTraverse(node.right, array)
array.append(node.value)
Time & Space Complexity
- Time: O(n) for all three traversals, where n is the number of nodes. Every node is visited exactly once.
- Space: O(n) total. The result array holds n values. The call stack uses O(h) space where h is the height of the tree (O(log n) for balanced, O(n) for skewed).
Key Insights
- In-order traversal of a BST always yields values in sorted ascending order. This is a direct consequence of the BST invariant.
- Pre-order traversal output can be used to uniquely reconstruct the original BST.
- Post-order traversal is useful when you need to process children before their parent (e.g., computing subtree sizes, freeing memory).
- All three traversals can also be implemented iteratively using an explicit stack, which avoids potential stack overflow for very deep trees.
Edge Cases
- Empty tree (root is null): return an empty array for all traversals.
- Single-node tree: all three traversals return an array with just that one value.
- Completely left-skewed or right-skewed tree: recursion depth equals n, which may cause stack overflow for very large n.
- Tree with duplicate values (if the BST allows them): traversal order depends on where duplicates are placed (left or right subtree).