Python Algorithms & Data Structures track

Lesson 17 · Part 5: Trees

Tree Traversal

Pre-order, in-order, post-order and level-order traversal, recursive vs iterative

Part 5: Trees4 min readFree lesson

Introduction

A tree is a special form of a connected graph without cycles. A tree with n nodes has exactly n-1 edges, and there is a unique path between any two nodes.

Applying graph traversal (DFS/BFS) to a tree yields different results depending on the traversal order. The reason this order is important:

  • Pre-order: Tree copying, serialization
  • In-order: Output sorted order in a binary search tree
  • Post-order: Tree deletion, calculating file system size
  • Level-order: BFS, shortest path, breadth-first processing
Tree vs General Graph
───────────────────────────────────────────────────────
Characteristic         Tree                 General Graph
───────────────────────────────────────────────────────
Cycle                 None                 May exist
Connectivity          Always connected    May be disconnected
Number of edges       n-1                 0 ~ n(n-1)/2
Root                  Exists (usually)    None
Parent-Child          Clear                No direction (undirected)
───────────────────────────────────────────────────────

Learning Goals

  1. Understand the structure of a tree (nodes, edges, root, leaf) and implement it in Python.
  2. Implement Preorder/Inorder/Postorder traversal both recursively and iteratively (using a stack).
  3. Implement level-order (BFS) and zigzag traversal using a queue, and explain the use cases of each traversal.

Key Concepts

Tree Node Structure

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

Text Art: Example Tree

1          ← Level 0 (Root)
            /   \
2       3      ← Level 1
         / \     / \
4   5   6   7    ← Level 2 (Leaf)

Pre-order traversal:   1 → 2 → 4 → 5 → 3 → 6 → 7
In-order traversal:    4 → 2 → 5 → 1 → 6 → 3 → 7
Post-order traversal:  4 → 5 → 2 → 6 → 7 → 3 → 1
Level-order traversal: 1 → 2 → 3 → 4 → 5 → 6 → 7

Comparison of Traversal Methods

┌─────────────────────┬──────────────┬──────────────────────────────────┐
│ Traversal Method     │ Time Complexity │ Space Complexity                      │
├─────────────────────┼──────────────┼──────────────────────────────────┤
│ Preorder (Recursive) │ O(n)           │ O(h) — Recursion stack (h=height)    │
│ Inorder (Recursive)  │ O(n)           │ O(h)                                  │
│ Postorder (Recursive)│ O(n)           │ O(h)                                  │
│ Preorder (Iterative) │ O(n)           │ O(h) — Explicit stack                │
│ Inorder (Iterative)  │ O(n)           │ O(h)                                  │
│ Postorder (Iterative)│ O(n)           │ O(h)                                  │
│ Level-order (BFS)    │ O(n)           │ O(w) — w=maximum width               │
└─────────────────────┴──────────────┴──────────────────────────────────┘

※ Balanced tree: h = O(log n),  Skewed tree (chain): h = O(n)
※ Complete binary tree maximum width: w = n/2 (last level)

Recursive Traversal Key Patterns

Pre-order:  [Current] → [Left] → [Right]
In-order:   [Left] → [Current] → [Right]
Post-order: [Left] → [Right] → [Current]

Iterative Traversal — Using Stack

Preorder Iteration:
  stack = [root]
  while stack:
      node = stack.pop()
      visit(node)
if node.right: stack.push(node.right)  ← Right first (processed later)
if node.left:  stack.push(node.left)   ← Left later (processed first)

Inorder Iteration:
  stack = [], curr = root
  while curr or stack:
      while curr:
          stack.push(curr)
          curr = curr.left
      curr = stack.pop()
      visit(curr)
      curr = curr.right

Level-order Traversal — Using Queue

queue = deque([root])
while queue:
    node = queue.popleft()
    visit(node)
    if node.left:  queue.append(node.left)
    if node.right: queue.append(node.right)

Example

File Contents
src/01_tree_node.py TreeNode class, tree creation, printing
src/02_recursive_traversal.py Preorder/Inorder/Postorder recursive traversal
src/03_iterative_traversal.py Preorder/Inorder/Postorder iterative (stack) traversal
src/04_level_order.py Level-order BFS, zigzag traversal

Common Mistakes

  1. Missing None check: If you omit the base case in a recursive function, if node is None: return, an AttributeError occurs
  2. Postorder iterative order confusion: Postorder iterative uses "reverse of preorder" or two stacks — simply changing stack order is wrong
  3. BFS without level separation: To group by level when queue.popleft(), you must first store the current level size using level_size = len(queue)
  4. Confusing height and depth: Height is from node to leaf, depth is from root to node — opposite directions
  5. Recursive overflow in skewed trees: Python default recursion limit is 1000 — for large input, use sys.setrecursionlimit() or iterative method

Summary

  • All tree traversals are time O(n), space O(h) (level-order is O(w))
  • Recursion is concise, but the risk of stack overflow exists in deep trees
  • Iterative (Stack/Queue) method uses an explicit stack to replace recursion
  • Inorder traversal = sorted output of binary search tree (connected to the next lesson)

Try It Yourself

  1. Try implementing maximum depth of a tree (max depth) using BFS and DFS respectively
  2. Write a function to compare if two trees are the same (using recursion)
  3. Determine if there exists a path whose path sum equals the target

Example files

The runnable files used in this lesson. Copy them into your own project and experiment.

src/01_tree_node.pyPython
#Topic: Tree Node Class and Tree Creation
#Time: O(n) — proportional to the number of nodes n
#Space: O(n) — stores all nodes

from __future__ import annotations
from collections import deque


class TreeNode:
    """Binary tree node."""

    def __init__(
        self,
        val: int = 0,
        left: TreeNode | None = None,
        right: TreeNode | None = None,
    ) -> None:
        self.val = val
        self.left = left
        self.right = right

    def __repr__(self) -> str:
        return f"TreeNode({self.val})"


def build_tree_from_list(values: list[int | None]) -> TreeNode | None:
    """Create a binary tree from a level-order list.

    Args:
        values: List of node values in level order (None = empty spot)

    Returns:
        Root node of the tree

    Time:  O(n)
    Space: O(n)"""
    if not values or values[0] is None:
        return None

    root = TreeNode(values[0])
    queue: deque[TreeNode] = deque([root])
    i = 1

    while queue and i < len(values):
        node = queue.popleft()

        #Left child
        if i < len(values) and values[i] is not None:
            node.left = TreeNode(values[i])
            queue.append(node.left)
        i += 1

        #Right child
        if i < len(values) and values[i] is not None:
            node.right = TreeNode(values[i])
            queue.append(node.right)
        i += 1

    return root


def tree_height(root: TreeNode | None) -> int:
    """Height of the tree (maximum number of edges from root to leaf).

    Time:  O(n)
    Space: O(h)"""
    if root is None:
        return -1  #Empty tree height = -1
    return 1 + max(tree_height(root.left), tree_height(root.right))


def count_nodes(root: TreeNode | None) -> int:
    """Number of nodes in the tree.

    Time:  O(n)
    Space: O(h)"""
    if root is None:
        return 0
    return 1 + count_nodes(root.left) + count_nodes(root.right)


def print_tree(root: TreeNode | None, level: int = 0, prefix: str = "Root:") -> None:
    """Print the tree as ASCII art.

    Time:  O(n)
    Space: O(h)"""
    if root is None:
        return
    print(" " * (level * 4) + prefix + str(root.val))
    if root.left or root.right:
        if root.left:
            print_tree(root.left, level + 1, "L── ")
        else:
            print(" " * ((level + 1) * 4) + "L── (None)")
        if root.right:
            print_tree(root.right, level + 1, "R── ")
        else:
            print(" " * ((level + 1) * 4) + "R── (None)")


#── Example Execution ──────────────────────────────────────────────────────────────
if __name__ == "__main__":
    #       1
    #      / \
    #     2   3
    #    / \ / \
    #   4  5 6  7
    values = [1, 2, 3, 4, 5, 6, 7]
    root = build_tree_from_list(values)

    print("=== Tree Structure ===")
    print_tree(root)

    print(f"\nTree Height: {tree_height(root)}")
    print(f"Number of Nodes:   {count_nodes(root)}")

    #Asymmetric Tree Test
    print("\n=== Asymmetric Tree ===")
    asym = build_tree_from_list([1, 2, 3, None, 4, None, 5])
    print_tree(asym)
    print(f"Height: {tree_height(asym)}, Number of Nodes: {count_nodes(asym)}")
src/02_recursive_traversal.pyPython
#Topic: Tree Traversal — Recursive Method (Pre-order/In-order/Post-order)
#Time: O(n) — Each node visited exactly once
#Space: O(h) — Recursion call stack depth = Tree height

from __future__ import annotations
import sys

sys.setrecursionlimit(10_000)

from collections import deque


class TreeNode:
    def __init__(self, val: int = 0,
                 left: "TreeNode | None" = None,
                 right: "TreeNode | None" = None) -> None:
        self.val = val
        self.left = left
        self.right = right


#── Recursive Traversal ──────────────────────────────────────────────────────────────

def preorder(root: TreeNode | None) -> list[int]:
    """Preorder traversal: Current → Left → Right.

    Uses: Tree copy, serialization, print
    Time:  O(n)
    Space: O(h)"""
    if root is None:
        return []
    return [root.val] + preorder(root.left) + preorder(root.right)


def inorder(root: TreeNode | None) -> list[int]:
    """Inorder traversal: Left → Current → Right.

    Uses: Ascending output in BST, expression tree evaluation
    Time:  O(n)
    Space: O(h)"""
    if root is None:
        return []
    return inorder(root.left) + [root.val] + inorder(root.right)


def postorder(root: TreeNode | None) -> list[int]:
    """Postorder traversal: Left → Right → Current.

    Uses: Tree deletion, folder size calculation, expression computation
    Time:  O(n)
    Space: O(h)"""
    if root is None:
        return []
    return postorder(root.left) + postorder(root.right) + [root.val]


#── In-place (passing result list as argument) version — Memory efficient ────────────────

def preorder_inplace(root: TreeNode | None, result: list[int]) -> None:
    """In-place preorder traversal (without creating a new list).

    Time:  O(n)
    Space: O(h)"""
    if root is None:
        return
    result.append(root.val)
    preorder_inplace(root.left, result)
    preorder_inplace(root.right, result)


def inorder_inplace(root: TreeNode | None, result: list[int]) -> None:
    """In-place inorder traversal."""
    if root is None:
        return
    inorder_inplace(root.left, result)
    result.append(root.val)
    inorder_inplace(root.right, result)


def postorder_inplace(root: TreeNode | None, result: list[int]) -> None:
    """In-place postorder traversal."""
    if root is None:
        return
    postorder_inplace(root.left, result)
    postorder_inplace(root.right, result)
    result.append(root.val)


#── Helper: Create tree from list ─────────────────────────────────────────────────────

def build(values: list[int | None]) -> TreeNode | None:
    if not values or values[0] is None:
        return None
    root = TreeNode(values[0])
    q: deque[TreeNode] = deque([root])
    i = 1
    while q and i < len(values):
        node = q.popleft()
        if i < len(values) and values[i] is not None:
            node.left = TreeNode(values[i])
            q.append(node.left)
        i += 1
        if i < len(values) and values[i] is not None:
            node.right = TreeNode(values[i])
            q.append(node.right)
        i += 1
    return root


#── Example Execution ──────────────────────────────────────────────────────────────
if __name__ == "__main__":
    #       1
    #      / \
    #     2   3
    #    / \ / \
    #   4  5 6  7
    root = build([1, 2, 3, 4, 5, 6, 7])

    print("=== Recursive Traversal Results ===")
    print(f"Pre-order:   {preorder(root)}")
    print(f"In-order:    {inorder(root)}")
    print(f"Post-order:  {postorder(root)}")

    print("=== In-place Traversal ===")
    res_pre: list[int] = []
    res_in: list[int] = []
    res_post: list[int] = []
    preorder_inplace(root, res_pre)
    inorder_inplace(root, res_in)
    postorder_inplace(root, res_post)
    print(f"Pre-order: {res_pre}")
    print(f"In-order: {res_in}")
    print(f"Post-order: {res_post}")

    #In BST, In-order = Sorted
    print("=== BST In-order Traversal = Sorted ===")
    #      4
    #     / \
    #    2   6
    #   / \ / \
    #  1  3 5  7
    bst = build([4, 2, 6, 1, 3, 5, 7])
    print(f"BST In-order Traversal: {inorder(bst)}  ← Ascending!")
src/03_iterative_traversal.pyPython
#Topic: Tree Traversal — Iterative (Stack) Method (Pre-order/In-order/Post-order)
#Time: O(n) — Each node visited exactly once
#Space: O(h) — Explicit stack size = tree height

from __future__ import annotations
from collections import deque


class TreeNode:
    def __init__(self, val: int = 0,
                 left: "TreeNode | None" = None,
                 right: "TreeNode | None" = None) -> None:
        self.val = val
        self.left = left
        self.right = right


#── Iterative Traversal ──────────────────────────────────────────────────────────────

def preorder_iterative(root: TreeNode | None) -> list[int]:
    """Iterative Preorder Traversal: Current → Left → Right.

    Key Idea:
      - Start by putting the root in the stack
      - pop → visit → push right → push left
      - Push left later so it's processed first (LIFO)

    Time:  O(n)
    Space: O(h)"""
    if root is None:
        return []

    result: list[int] = []
    stack: list[TreeNode] = [root]

    while stack:
        node = stack.pop()
        result.append(node.val)

        #Push right first → left is popped first
        if node.right:
            stack.append(node.right)
        if node.left:
            stack.append(node.left)

    return result


def inorder_iterative(root: TreeNode | None) -> list[int]:
    """Iterative Inorder Traversal: Left → Current → Right.

    Key Idea:
      - Move to the leftmost node using a curr pointer while pushing onto the stack
      - Reach the leftmost → pop → visit → curr = curr.right
      - Repeat for the right subtree

    Time:  O(n)
    Space: O(h)"""
    result: list[int] = []
    stack: list[TreeNode] = []
    curr: TreeNode | None = root

    while curr or stack:
        #Move to the far left
        while curr:
            stack.append(curr)
            curr = curr.left

        #Visit and move right
        curr = stack.pop()
        result.append(curr.val)
        curr = curr.right

    return result


def postorder_iterative(root: TreeNode | None) -> list[int]:
    """Iterative Postorder Traversal: Left → Right → Current.

    Key Idea (Using Reverse):
      - Reverse a preorder traversal (Current→Right→Left) to get postorder
      - That is, pop from stack → add to result → push left → push right
      - Reverse the result at the end

    Time:  O(n)
    Space: O(h)"""
    if root is None:
        return []

    result: list[int] = []
    stack: list[TreeNode] = [root]

    while stack:
        node = stack.pop()
        result.append(node.val)   #Current visit (reverse at the end since it's in reverse order)

        if node.left:             #Push left first (right is popped first)
            stack.append(node.left)
        if node.right:
            stack.append(node.right)

    result.reverse()              #Current → Right → Left → Reverse → Left → Right → Current
    return result


def postorder_two_stack(root: TreeNode | None) -> list[int]:
    """Postorder Traversal Using Two Stacks (For Educational Purpose).

    Time:  O(n)
    Space: O(n) — the second stack can store up to n elements"""
    if root is None:
        return []

    stack1: list[TreeNode] = [root]
    stack2: list[int] = []

    while stack1:
        node = stack1.pop()
        stack2.append(node.val)

        if node.left:
            stack1.append(node.left)
        if node.right:
            stack1.append(node.right)

    return stack2[::-1]


#── Helper: Create tree from list ─────────────────────────────────────────────────────

def build(values: list[int | None]) -> TreeNode | None:
    if not values or values[0] is None:
        return None
    root = TreeNode(values[0])
    q: deque[TreeNode] = deque([root])
    i = 1
    while q and i < len(values):
        node = q.popleft()
        if i < len(values) and values[i] is not None:
            node.left = TreeNode(values[i])
            q.append(node.left)
        i += 1
        if i < len(values) and values[i] is not None:
            node.right = TreeNode(values[i])
            q.append(node.right)
        i += 1
    return root


#── Example Execution ──────────────────────────────────────────────────────────────
if __name__ == "__main__":
    #       1
    #      / \
    #     2   3
    #    / \ / \
    #   4  5 6  7
    root = build([1, 2, 3, 4, 5, 6, 7])

    print("=== Iterative (Stack) Traversal Results ===")
    print(f"Pre-order:   {preorder_iterative(root)}")
    print(f"In-order:    {inorder_iterative(root)}")
    print(f"Post-order:  {postorder_iterative(root)}")
    print(f"Post-order (Two Stacks):     {postorder_two_stack(root)}")

    print("\n=== Recursive vs Iterative Result Comparison ===")
    from src.02_recursive_traversal import preorder, inorder, postorder  # noqa

    #Direct comparison (should be the same)
    assert preorder_iterative(root) == [1, 2, 4, 5, 3, 6, 7]
    assert inorder_iterative(root) == [4, 2, 5, 1, 6, 3, 7]
    assert postorder_iterative(root) == [4, 5, 2, 6, 7, 3, 1]
    print("All results match ✓")

    #Skewed tree (left-only)
    print("\n=== Skewed Tree ===")
    #  1
    #   \
    #    2
    #     \
    #      3
    skewed = build([1, None, 2, None, None, None, 3])
    #Direct construction
    skewed = TreeNode(1)
    skewed.right = TreeNode(2)
    skewed.right.right = TreeNode(3)
    print(f"In-order (right-skewed): {inorder_iterative(skewed)}")
src/04_level_order.pyPython
#Topic: Level Order Traversal (BFS), Grouping by Level, Zigzag Traversal
#Time: O(n) — Each node visited exactly once
#Space: O(w) — w = maximum width (in a complete binary tree w ≈ n/2)

from __future__ import annotations
from collections import deque


class TreeNode:
    def __init__(self, val: int = 0,
                 left: "TreeNode | None" = None,
                 right: "TreeNode | None" = None) -> None:
        self.val = val
        self.left = left
        self.right = right


def level_order(root: TreeNode | None) -> list[int]:
    """Basic Level Order Traversal (BFS).

    Time:  O(n)
    Space: O(w) — max size of queue = maximum width"""
    if root is None:
        return []

    result: list[int] = []
    queue: deque[TreeNode] = 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


def level_order_by_levels(root: TreeNode | None) -> list[list[int]]:
    """Level-wise Grouping BFS.

    Key: Fix the current level size with len(queue) at the start of the loop

    Time:  O(n)
    Space: O(w)"""
    if root is None:
        return []

    result: list[list[int]] = []
    queue: deque[TreeNode] = deque([root])

    while queue:
        level_size = len(queue)   #Current number of nodes at the level (important!)
        level: list[int] = []

        for _ in range(level_size):
            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


def zigzag_level_order(root: TreeNode | None) -> list[list[int]]:
    """Zigzag (Spiral) Level Order Traversal.

    Even levels: left → right (forward)
    Odd levels: right → left (reverse)

    Time:  O(n)
    Space: O(w)"""
    if root is None:
        return []

    result: list[list[int]] = []
    queue: deque[TreeNode] = deque([root])
    left_to_right = True   #First level is forward

    while queue:
        level_size = len(queue)
        level: list[int] = []

        for _ in range(level_size):
            node = queue.popleft()
            level.append(node.val)

            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)

        if not left_to_right:
            level.reverse()   #Reverse level is reversed

        result.append(level)
        left_to_right = not left_to_right   #Change of direction

    return result


def right_side_view(root: TreeNode | None) -> list[int]:
    """Nodes visible from the right (last node of each level).

    Time:  O(n)
    Space: O(w)"""
    if root is None:
        return []

    result: list[int] = []
    queue: deque[TreeNode] = deque([root])

    while queue:
        level_size = len(queue)

        for i in range(level_size):
            node = queue.popleft()

            if i == level_size - 1:   #Last node of the level
                result.append(node.val)

            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)

    return result


def max_depth_bfs(root: TreeNode | None) -> int:
    """Find Maximum Depth of Tree using BFS.

    Time:  O(n)
    Space: O(w)"""
    if root is None:
        return 0

    depth = 0
    queue: deque[TreeNode] = deque([root])

    while queue:
        depth += 1
        for _ in range(len(queue)):
            node = queue.popleft()
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)

    return depth


#── Helper: Create tree from list ─────────────────────────────────────────────────────

def build(values: list[int | None]) -> TreeNode | None:
    if not values or values[0] is None:
        return None
    root = TreeNode(values[0])
    q: deque[TreeNode] = deque([root])
    i = 1
    while q and i < len(values):
        node = q.popleft()
        if i < len(values) and values[i] is not None:
            node.left = TreeNode(values[i])
            q.append(node.left)
        i += 1
        if i < len(values) and values[i] is not None:
            node.right = TreeNode(values[i])
            q.append(node.right)
        i += 1
    return root


#── Example Execution ──────────────────────────────────────────────────────────────
if __name__ == "__main__":
    #        1
    #       / \
    #      2   3
    #     / \   \
    #    4   5   6
    root = build([1, 2, 3, 4, 5, None, 6])

    print("=== Level Order Traversal ===")
    print(f"Basic BFS:         {level_order(root)}")
    print(f"Grouped by Levels: {level_order_by_levels(root)}")
    print(f"Zigzag Traversal: {zigzag_level_order(root)}")
    print(f"Right Side View:  {right_side_view(root)}")
    print(f"Maximum Depth (BFS):  {max_depth_bfs(root)}")

    print()
    print("=== Complete Binary Tree ===")
    #       1
    #      / \
    #     2   3
    #    / \ / \
    #   4  5 6  7
    full = build([1, 2, 3, 4, 5, 6, 7])
    levels = level_order_by_levels(full)
    for i, lv in enumerate(levels):
        print(f"Level {i}: {lv}")

    print()
    print("=== Zigzag Visualization ===")
    #1          Level 0: → [1]
    #         /   \
    #2     3       Level 1: ← [3, 2]
    #       / \   / \
    #4   5 6   7     Level 2: → [4, 5, 6, 7]
    zz = zigzag_level_order(full)
    for i, lv in enumerate(zz):
        direction = "→" if i % 2 == 0 else "←"
        print(f"Level {i} ({direction}): {lv}")

Assignment

Problem 1: Baekjoon 1991 — Tree Traversal (Silver I)

Link: https://www.acmicpc.net/problem/1991

Problem Summary

When a binary tree is represented by letters (A~Z), output the result of Preorder/Inorder/Postorder traversal.

Input format

7
A B C
B D .
C E F
D . .
E . . 
F . G
G . .

(. = no child)

Output Format

ABDCEFG    ← Preorder
DBAECFG    ← Inorder
DBEGFCA    ← Postorder

Key Points

  • Represent the tree with a dictionary: tree[node] = (left, right)
  • . is treated as None
  • Apply recursion traversal as is

Time/Space Complexity

  • Time: O(n) — number of nodes n
  • Space: O(n) — dictionary + recursion stack

Problem 2: Baekjoon 11725 — Find Parents in a Tree (Silver II)

Link: https://www.acmicpc.net/problem/11725

Problem Summary

In a tree with root 1, find the parent of each node.

Input format

7
1 6
6 3
3 5
4 1
2 4
4 7

Output Format

4
6
1
3
1
4

(In order of parents of nodes 2 through n)

Key Points

  • Input as undirected graph → traverse from root (1) With-BFS/DFS
  • Update the parent array parent[v] = u
  • Must mark visited (to prevent infinite loops)

Time/Space Complexity

  • Time: O(n) — BFS/DFS
  • Space: O(n) — adjacency list + parent array

Solution File

  • boj_1991.py
  • boj_11725.py
Show the reference solution

Try the assignment yourself first — comparing your attempt with a working solution is where most of the learning happens.

boj_11725.pyPython
#Baekjoon 11725 — Finding the Parent of a Tree
# https://www.acmicpc.net/problem/11725
# Time: O(n)   Space: O(n)

import sys
from collections import deque

input = sys.stdin.readline


def solve() -> None:
    n = int(input())
    graph: list[list[int]] = [[] for _ in range(n + 1)]

    for _ in range(n - 1):
        u, v = map(int, input().split())
        graph[u].append(v)
        graph[v].append(u)

    parent = [0] * (n + 1)
    visited = [False] * (n + 1)

    #BFS: Start from the root (1)
    queue: deque[int] = deque([1])
    visited[1] = True

    while queue:
        node = queue.popleft()
        for neighbor in graph[node]:
            if not visited[neighbor]:
                visited[neighbor] = True
                parent[neighbor] = node
                queue.append(neighbor)

    #Print the parents of nodes 2 to n
    result = [str(parent[i]) for i in range(2, n + 1)]
    sys.stdout.write("\n".join(result) + "\n")


solve()
boj_1991.pyPython
#Baekjoon 1991 — Tree Traversal
# https://www.acmicpc.net/problem/1991
# Time: O(n)   Space: O(n)

import sys

input = sys.stdin.readline


def solve() -> None:
    n = int(input())
    tree: dict[str, tuple[str | None, str | None]] = {}

    for _ in range(n):
        parts = input().split()
        node = parts[0]
        left = parts[1] if parts[1] != "." else None
        right = parts[2] if parts[2] != "." else None
        tree[node] = (left, right)

    def preorder(node: str | None) -> None:
        if node is None:
            return
        print(node, end="")
        left, right = tree[node]
        preorder(left)
        preorder(right)

    def inorder(node: str | None) -> None:
        if node is None:
            return
        left, right = tree[node]
        inorder(left)
        print(node, end="")
        inorder(right)

    def postorder(node: str | None) -> None:
        if node is None:
            return
        left, right = tree[node]
        postorder(left)
        postorder(right)
        print(node, end="")

    preorder("A")
    print()
    inorder("A")
    print()
    postorder("A")
    print()


solve()

Learn this lesson with a mentor

Work through the Python Algorithms & Data Structures track on your own, or join a guided cohort at our Pitampura campus and online.

Call NowEnroll Now