Implement Post-order Traversal of a Binary Tree

problem-solving
Published

January 20, 2024

Post-order traversal is one of the three fundamental ways to traverse a binary tree (the others being pre-order and in-order). Understanding tree traversal is important for various algorithms and data structure manipulations. This post focuses on efficiently implementing post-order traversal in Python, providing clear explanations and code examples.

Understanding Post-order Traversal

Post-order traversal visits the nodes of a binary tree in a specific order: left subtree, right subtree, root. This means that the root node is always processed after its children.

Recursive Approach

The most intuitive way to implement post-order traversal is recursively. The recursive function calls itself on the left and right subtrees before processing the root node’s data.

class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None

def postorder_recursive(node):
    if node:
        postorder_recursive(node.left)
        postorder_recursive(node.right)
        print(node.data, end=" ")

# Example usage:
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.left.right = Node(5)

print("Post-order traversal (recursive):")
postorder_recursive(root)  # Output: 4 5 2 3 1

Iterative Approach using a Stack

While recursion is elegant, it can be less efficient for very deep trees due to stack overflow issues. An iterative approach using a stack provides a more efficient solution.

def postorder_iterative(node):
    if node is None:
        return

    stack = []
    while True:
        while node:
            if node.right:
                stack.append(node.right)
            stack.append(node)
            node = node.left
        node = stack.pop()
        if node.right and stack and node.right == stack[-1]:
            stack.pop()
            stack.append(node)
            node = node.right
        else:
            print(node.data, end=" ")
            node = None
            if not stack:
                break

print("\nPost-order traversal (iterative):")
postorder_iterative(root) # Output: 4 5 2 3 1

This iterative method uses a stack to mimic the recursive call stack, ensuring that nodes are processed in the correct post-order sequence even for deep trees. Note the careful handling of the right subtree to ensure proper sequencing.

Choosing the Right Approach

The recursive approach is often preferred for its simplicity and readability. However, for large trees or situations where stack overflow is a concern, the iterative approach using a stack is a more efficient alternative. The choice depends on the specific application and constraints.