← Back to Course

Template

Tree Data Structures Overview

Tree Data Structures

Binary Trees, BSTs, and N-ary Trees

1. Introduction

A tree is a hierarchical data structure consisting of nodes connected by edges, with one node designated as the root. Each node can have children nodes, and a node with no children is called a leaf. In a tree, every child has exactly one parent (except the root, which has none).

A binary tree is a special case where each node has at most two children (left and right). A binary search tree (BST) is a binary tree with an ordering property: for each node, all values in its left subtree are smaller, and all values in its right subtree are larger. More generally, an N-ary tree is a rooted tree in which each node can have up to N children.

Tree-based questions are very common in coding interviews. Keywords hinting at tree solutions include “nodes,” “children/parent,” “root/leaf,” “left/right child,” or traversal terms like “preorder,” “inorder,” “postorder,” and “level-order.”

2. Core Idea / Mental Model

A tree can be thought of as a hierarchy where each subtree is a smaller instance of the problem, naturally lending itself to recursive thinking. A good mental model is to consider each node as the root of its own subtree.

Analogies: Family tree, company org chart, file system directory tree.

Common Traversal Patterns:

  • Depth-First Search (DFS): Implemented via recursion or an explicit stack.
    • Pre-order: Root -> Left -> Right
    • In-order: Left -> Root -> Right (yields sorted order in a BST)
    • Post-order: Left -> Right -> Root
  • Breadth-First Search (BFS): Implemented with a queue, processing nodes level by level (level-order traversal). Useful for shortest path in unweighted trees.

Problem-Solving Strategy:

  1. Recursion first: Define the problem in terms of subproblems on children.
  2. Identify traversal type: DFS for full exploration/path sums, BFS for levels/shortest path.
  3. Top-down vs. Bottom-up: Accumulate results going down (pre-order) or compute from children up (post-order).
  4. Consider edge cases: Empty tree, single-node tree, skewed trees.

3. Base Template (Python Tree Traversals)

Below is a Python template for common tree traversals, using a simple TreeNode class.

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

# Pre-order Traversal (Root -> Left -> Right)
def preorder_traversal(root: TreeNode):
    if root is None: return []
    result = [root.val]
    result.extend(preorder_traversal(root.left))
    result.extend(preorder_traversal(root.right))
    return result

# In-order Traversal (Left -> Root -> Right)
def inorder_traversal(root: TreeNode):
    if root is None: return []
    result = []
    result.extend(inorder_traversal(root.left))
    result.append(root.val)
    result.extend(inorder_traversal(root.right))
    return result

# Post-order Traversal (Left -> Right -> Root)
def postorder_traversal(root: TreeNode):
    if root is None: return []
    result = []
    result.extend(postorder_traversal(root.left))
    result.extend(postorder_traversal(root.right))
    result.append(root.val)
    return result

# Level-order Traversal (BFS)
from collections import deque
def level_order_traversal(root: TreeNode):
    if root is None: 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
Dry Run Example (Pre-order for Tree: 1 / (2, 3)):
  1. preorder(1): result = [1]
  2. Call preorder(2): result = [2], returns [2]
  3. result.extend([2]) -> result = [1, 2]
  4. Call preorder(3): result = [3], returns [3]
  5. result.extend([3]) -> result = [1, 2, 3]
  6. Return [1, 2, 3]

4. Interactive Animation (Pre-order Traversal)

The animation below demonstrates Pre-order Depth-First Search (DFS) on a sample binary tree. Observe how the algorithm visits the current node, then its left subtree, then its right subtree. The "call stack" visually represents the recursion depth.

Sample Binary Tree for Traversal
Example tree: Root 10; Left child 5 (with children 3, 7); Right child 15 (with right child 18).
Pre-order Traversal Trace (Root -> Left -> Right):
  1. Visit 10. Stack: [10]. Order: [10].
  2. Go Left. Visit 5. Stack: [10, 5]. Order: [10, 5].
  3. Go Left. Visit 3. Stack: [10, 5, 3]. Order: [10, 5, 3]. (3 is leaf, backtrack)
  4. Back to 5. Go Right. Visit 7. Stack: [10, 5, 7]. Order: [10, 5, 3, 7]. (7 is leaf, backtrack)
  5. Back to 5 (done with children). Back to 10.
  6. Go Right. Visit 15. Stack: [10, 15]. Order: [10, 5, 3, 7, 15].
  7. Go Left (None). Go Right. Visit 18. Stack: [10, 15, 18]. Order: [10, 5, 3, 7, 15, 18]. (18 is leaf, backtrack)
  8. Done. Final Order: [10, 5, 3, 7, 15, 18].
371851510
Call Stack: [], Order: []

Click 'Start Pre-order Animation'.

5. Time & Space Complexity

For an n-node tree:

  • Time Complexity (All Traversals): O(n) - each node visited once.
  • Space Complexity (DFS - Recursive): O(h) for call stack, where h is tree height. Worst case O(n) for skewed tree, best/average O(log n) for balanced tree.
  • Space Complexity (DFS - Iterative with Stack): O(h), similar to recursive.
  • Space Complexity (BFS - Level-order): O(w) where w is max width of tree. Worst case O(n) for a complete tree.

(Output list space is O(n) if storing all node values.)

6. Common Pitfalls

  • Incorrect or Missing Base Case: Not handling None nodes in recursion.
  • Off-by-One Errors: In height/depth calculations.
  • Infinite Recursion / Cycles: Usually not an issue for standard trees but be careful if modifying structure or treating as general graph.
  • Null Child Handling: Accessing properties of None children (e.g., node.left.val without checking node.left).
  • Using Wrong Traversal Approach: E.g., using DFS for shortest path when BFS is better.
  • Mistaking Binary Tree vs BST: Assuming BST properties for a general binary tree.
  • BST Edge Cases: Incorrect min/max bounds for validation, mishandling duplicates.
  • Not Accounting for Recursion Return Values: Forgetting to use or propagate results from recursive calls.
  • Edge Cases & Skewed Trees: Test with empty, single-node, and skewed trees.

7. Frequently Asked Tree Problems (LeetCode)

The following are some of the most frequently asked LeetCode problems involving trees:

Problem (LeetCode) Difficulty
Maximum Depth of Binary TreeEasy
Same TreeEasy
Symmetric TreeEasy
Balanced Binary TreeEasy
Invert Binary TreeEasy
Binary Tree Level Order TraversalMedium
Binary Tree Zigzag Level Order TraversalMedium
Binary Tree Right Side ViewMedium
Validate Binary Search TreeMedium
Subtree of Another TreeEasy
Lowest Common Ancestor of a Binary TreeMedium
Binary Tree Maximum Path SumHard
Serialize and Deserialize Binary TreeHard
Construct Binary Tree from Preorder and Inorder TraversalMedium
Path SumEasy
Kth Smallest Element in a BSTMedium

Solving these problems will solidify your understanding of tree fundamentals.

© Tree Data Structures Overview. Content adapted for educational purposes.

We use cookies to improve your experience. By clicking “Accept” you consent to the use of cookies. Read our Privacy Policy.