Description
Binary tree traversal teaches us the ways we can traverse a binary tree. This concept is important to solve binary tree problems. There are 4 main types of tree traversal
- In order traversal: Where we visit left sub-tree 1st, then parent node and in the end right sub-tree
- Pre order traversal: Where we visit parent node 1st, then left sub-tree and in the end right sub-tree
- Post order traversal: Where we visit left sub-tree 1st, then right sub-tree and in the end parent node
- Level order traversal: Where we visit elements level by level, from left to right.
Usage
Following are few problems that utilizes these traversal approaches
- Binary Tree Paths
- Kth Smallest Element in a BST
- Binary Tree Maximum Path Sum
- Binary Tree Level Order Traversal II
In order traversal
In-order traversal method traverse a binary tree in this order
- Recursively process left sub-tree nodes
- Process current parent node
- Recursively process right sub-tree nodes
The name signifies that tree is accessed in order, the way it is represented visually, Left -> Root -> Right.
This is the binary tree version of Depth First Search. It can be used to get sorted array from a Binary Search Tree.
Binary Search tree is a special type of Binary tree where all nodes in the left sub-tree are smaller than the parent node and all nodes in the right sub-tree are larger than the parent node.
This can provide optimized time complexity of to search, insert and delete operation in a balanced tree. Otherwise it degrades to .
Code
class Node:
def __init__(self, val: int = None, left: Self = None, right: Self = None):
self.val = val
self.left = left
self.right = right
def _in_order(node: Node, result: list) -> list[int]:
if not node:
return
_in_order(node.left, result)
result.append(node.val)
_in_order(node.right, result)
def in_order(root: Node):
result = list()
_in_order(root, result)
return result
Complexity
- Each node is visited only once
- Size of the result is of size N and there are a maximum of H stack frames due to recursion.
Pre order traversal
Pre-order traversal method traverse a binary tree in this order
- Process current parent node
- Recursively process left sub-tree nodes
- Recursively process right sub-tree nodes
The name signifies that root of a tree is accessed before left and right children, i.e. Root -> Left -> Right.
Code
class Node:
def __init__(self, val: int = None, left: Self = None, right: Self = None):
self.val = val
self.left = left
self.right = right
def _pre_order(node: Node, result: list) -> list[int]:
if not node:
return
result.append(node.val)
_pre_order(node.left, result)
_pre_order(node.right, result)
def pre_order(root: Node):
result = list()
_pre_order(root, result)
return result
Complexity
- Each node is visited only once
- Size of the result is of size N and there are maximum a maximum of H stack frames due to recursion.
Post order traversal
Post-order traversal method traverse a binary tree in this order
- Recursively process left sub-tree nodes
- Recursively process right sub-tree nodes
- Process current parent node
The name signifies that root of a tree is accessed after left and right children, i.e. Left -> Right -> Root.
Code
class Node:
def __init__(self, val: int = None, left: Self = None, right: Self = None):
self.val = val
self.left = left
self.right = right
def _post_order(node: Node, result: list) -> list[int]:
if not node:
return
_post_order(node.left, result)
_post_order(node.right, result)
result.append(node.val)
def post_order(root: Node):
result = list()
_post_order(root, result)
return result
Complexity
- Each node is visited only once
- Size of the result is of size N and there are maximum a maximum of H stack frames due to recursion.
Level order traversal
Level-order traversal method traverse a binary tree in order of depth, with 0 level being processed first and from left to right in same level.
Code
from collections import deque
class Node:
def __init__(self, val: int = None, left: Self = None, right: Self = None):
self.val = val
self.left = left
self.right = right
def level_order(root: Node):
result = list()
queue = deque([root])
while len(queue):
node = queue.popleft()
result.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return result
Complexity
- Each node is visited only once
- Size of the result is of size N and queue can have almost W elements at a times.