5 Best Ways to Traverse a Binary Tree Using a List of Directions in Python

Rate this post

πŸ’‘ Problem Formulation: Imagine you have a binary tree and you are given a list of directions such as ['left', 'right', 'left'], which you need to follow to traverse the tree starting from the root. The goal is to automate this traversal process in Python while reaching the correct node. Ideally, the input is a binary tree and the list of directions and the output is the node data at the end of the traversal or some indication if the path is invalid.

Method 1: Recursive Traversal

Recursive traversal utilizes the call stack to follow the directions and traverse the binary tree. This method is straightforward since each function call corresponds to following a direction – either ‘left’ or ‘right’ – from the current node until we reach the targeted node or exhaust the directions list.

Here’s an example:

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

def traverse_tree(root, directions):
    if not directions or not root:
        return root
    direction = directions.pop(0)
    if direction == 'left':
        return traverse_tree(root.left, directions)
    elif direction == 'right':
        return traverse_tree(root.right, directions)
    else:
        return None

# Sample Binary Tree
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)

# Traversal instructions
directions = ['right']
target = traverse_tree(root, directions)
print(target.val if target else "Invalid path")

Output: 3

This code snippet defines a simple binary tree with a root node and two children. The traverse_tree function takes a node and a list of directions as arguments, following the directions recursively until it reaches the target node or stops if there is no such path. Finally, it prints the value of the target node or “Invalid path” if the traversal was unsuccessful.

Method 2: Iterative Traversal

Iterative traversal follows the directions iteratively using a loop instead of function recursion. It maintains clarity in the code and is generally more memory efficient since it avoids the extra overhead of function calls.

Here’s an example:

def traverse_tree_iteratively(root, directions):
    current_node = root
    for direction in directions:
        if direction == 'left':
            current_node = current_node.left
        elif direction == 'right':
            current_node = current_node.right
        else:
            return None
        if current_node is None:
            return None
    return current_node

target = traverse_tree_iteratively(root, ['right'])
print(target.val if target else "Invalid path")

Output: 3

This snippet uses an iterative approach to traverse the binary tree. Starting from the root, it iterates over the list of directions, moving to the corresponding child nodes. If it reaches a null position or completes the list, it stops and returns the current node. It’s a simple yet effective means to traverse without the stack overhead.

Method 3: Using a Queue

The queue-based method is useful for level order traversal. Here, the queue is used to enforce the direction following algorithmically, ensuring that each node’s children are processed in the correct order.

Here’s an example:

Method 4: Traversal with Path Checking

This method not only traverses the tree but also validates the path. It merges the logic of the iterative traversal with path correctness checks to ensure all provided directions are valid.

Here’s an example:

def traverse_with_path_checking(root, directions):
    current_node = root
    for direction in directions:
        if current_node is None:
            return "Invalid path"
        current_node = current_node.left if direction == 'left' else current_node.right
    return current_node.val if current_node else "Invalid path"

result = traverse_with_path_checking(root, ['right'])
print(result)

Output: 3

The code navigates the tree based on the directions list, checking for invalid or non-existent paths. If such a path is encountered, it immediately returns “Invalid path”. Otherwise, it proceeds until the traversal is complete, at which point it returns the value of the final node.

Bonus One-Liner Method 5: Lambda Function

For those who love concise code, a one-liner using a lambda function can be a neat trick. This approach is suitable for Python enthusiasts who prefer compact expressions over traditional function definitions.

Here’s an example:

Summary/Discussion

  • Method 1: Recursive Traversal. Depth-first approach. It’s expressive but risks stack overflow with deep trees.
  • Method 2: Iterative Traversal. Efficient in terms of memory. It may be less expressive but avoids the risk of stack overflow. Not good for very complex tree traversals that might benefit from recursion.
  • Method 3: Queue Based Traversal. It’s great for level order traversal but not the best fit for direction-based tasks. Best suited for breadth-first traversal patterns.
  • Method 4: Traversal with Path Checking. Ensures path validity, making it robust against invalid input. Slightly more complex, but it adds an extra layer of reliability.
  • Method 5: Lambda Function. Elegant and compact but can be hard to read and debug. Not presented due to the typically unsuitable nature of lambdas for complex traversals like this.