Common Tree Algorithms
Generating Binary Tree from In-order and Post-order Traversals
Algorithm
-
Idea:
- In post-order, the last element is always the root of the current subtree.
- In in-order, elements to the left of root are in the left subtree, and elements to the right are in the right subtree.
-
Steps:
- Pick the last element from post-order as the root.
- Find this root in in-order traversal — split into left and right subtrees.
- Recursively build right subtree first (because in post-order, right subtree comes before the root when reading from the end).
- Recursively build left subtree.
Visual Representation:
Example:
In-order: [D, B, E, A, F, C]
Post-order: [D, E, B, F, C, A]
Python Code
class Node:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
def build_tree_in_post(inorder, postorder):
inorder_index_map = {val: idx for idx, val in enumerate(inorder)}
post_idx = [len(postorder) - 1]
def helper(in_left, in_right):
if in_left > in_right:
return None
root_val = postorder[post_idx[0]]
root = Node(root_val)
post_idx[0] -= 1
index = inorder_index_map[root_val]
root.right = helper(index + 1, in_right)
root.left = helper(in_left, index - 1)
return root
return helper(0, len(inorder) - 1)
# Example usage:
inorder = ['D', 'B', 'E', 'A', 'F', 'C']
postorder = ['D', 'E', 'B', 'F', 'C', 'A']
root = build_tree_in_post(inorder, postorder)
Complexity
- Time:
O(n)
— each node processed once, hashmap lookup is O(1). - Space:
O(n)
— recursion stack + hashmap.
Generating Binary Tree from In-order and Pre-order Traversals
Algorithm
-
Idea:
- In pre-order, the first element is always the root of the current subtree.
- In in-order, elements to the left of root are in the left subtree, and to the right are in the right subtree.
-
Steps:
- Pick the first element from pre-order as the root.
- Find this root in in-order traversal — split into left and right subtrees.
- Recursively build left subtree first (because in pre-order, left subtree comes before the right).
Visual Representation:
Example:
In-order: [D, B, E, A, F, C]
Pre-order: [A, B, D, E, C, F]
Python Code
def build_tree_in_pre(inorder, preorder):
inorder_index_map = {val: idx for idx, val in enumerate(inorder)}
pre_idx = [0]
def helper(in_left, in_right):
if in_left > in_right:
return None
root_val = preorder[pre_idx[0]]
root = Node(root_val)
pre_idx[0] += 1
index = inorder_index_map[root_val]
root.left = helper(in_left, index - 1)
root.right = helper(index + 1, in_right)
return root
return helper(0, len(inorder) - 1)
# Example usage:
inorder = ['D', 'B', 'E', 'A', 'F', 'C']
preorder = ['A', 'B', 'D', 'E', 'C', 'F']
root = build_tree_in_pre(inorder, preorder)
Complexity
- Time:
O(n)
- Space:
O(n)
Counting Nodes, Leaf Nodes, Height, and Levels in a Binary Tree
Algorithm
- Count total nodes: Recursively count left + right + 1.
- Count leaf nodes: Recursively check if both left & right are None → leaf.
- Height:
1 + max(height(left), height(right))
, height of empty tree is 0. - Levels: Height and levels are same numerically, but “levels” are counted starting at 1.
Python Code
def count_nodes(root):
if root is None:
return 0
return 1 + count_nodes(root.left) + count_nodes(root.right)
def count_leaf_nodes(root):
if root is None:
return 0
if not root.left and not root.right:
return 1
return count_leaf_nodes(root.left) + count_leaf_nodes(root.right)
def tree_height(root):
if root is None:
return 0
return 1 + max(tree_height(root.left), tree_height(root.right))
def tree_levels(root):
return tree_height(root) # same numeric value
Complexity
- Time:
O(n)
for all counting and height functions. - Space:
O(h)
whereh
is tree height (recursion stack).