Inorder Traversal of a Binary Tree using Iteration
Problem and examples
| Input Tree | Inorder Traversal Output | Description |
|---|---|---|
| [1, 2, 3, 4, 5, null, 6] | [4, 2, 5, 1, 3, 6] | Standard case: Tree with both left and right children and missing node |
| [1] | [1] | Edge case: Tree with a single node |
| [] | [] | Edge case: Empty tree with no nodes |
| [1, 2, null, 3, null, null, null, 4] | [4, 3, 2, 1] | Edge case: Deep left-skewed tree |
| [1, null, 2, null, null, null, 3] | [1, 2, 3] | Edge case: Deep right-skewed tree |
| [5, 3, 7, 2, 4, 6, 8] | [2, 3, 4, 5, 6, 7, 8] | Balanced binary search tree (BST): inorder gives sorted values |
Explore Inorder Traversal of a Binary Tree - Iteration
Load an example or enter your own input. Use the player controls to follow each change.
Understanding the Problem
Inorder traversal is a common way to visit all the nodes in a binary tree. The order of traversal is: Left subtree → Node → Right subtree. When done recursively, it’s straightforward. But when we try to do it iteratively, we need to simulate the call stack manually using a data structure — typically a stack.
Our goal is to traverse the binary tree in inorder sequence using an iterative approach, even in complex or edge structures like skewed trees or empty trees.
Step-by-Step Solution with Example
Step 1: Use a Stack to Simulate Recursion
We use a stack to keep track of nodes while going left. This mimics the call stack of a recursive solution. We keep pushing nodes onto the stack as we go left.
Step 2: Start from the Root
Initialize a stack, and set the current pointer to the root. As long as the current node is not null, push it onto the stack and move left.
Step 3: Process the Leftmost Node
Once current becomes null, we pop a node from the stack — this is the node we visit next. Add its value to the result list.
Step 4: Move to the Right Subtree
After visiting a node, move the current pointer to its right child. Repeat the process — push all left children of the new current onto the stack.
Step 5: Loop Until Done
Repeat steps 2–4 until the stack is empty and the current pointer is null. This ensures all nodes are visited in inorder.
Example Walkthrough
Given binary tree:
1
/ 2 3
/ 4 5
Inorder traversal: [4, 2, 5, 1, 3]
Steps:
- Start at root (1), push to stack → go left to 2 → push → go left to 4 → push → no more left.
- Pop 4, visit it → move to null → pop 2, visit it → move to right (5)
- Push 5 → no left → pop and visit 5 → move to null
- Pop 1, visit it → move to right (3) → push → no left → pop and visit
Final output: [4, 2, 5, 1, 3]
Edge Cases
Left-Skewed Tree
Example: 4 → 3 → 2 → 1 (all nodes only have left children). We keep pushing nodes until we reach null, then pop and visit nodes bottom-up. Result is: [1, 2, 3, 4]
Right-Skewed Tree
Example: 1 → 2 → 3 → 4 (only right children). There are no left nodes to push, so we visit the node directly and move to the right. Result is: [1, 2, 3, 4]
Single Node Tree
Only root node exists. We visit it, and there are no left or right children. Output is simply: [node.val]
Empty Tree
If the root is null, then there are no nodes to traverse. Return an empty list. This must be handled explicitly to avoid null reference errors.
Finally
Inorder traversal using iteration may seem tricky at first, but with a stack and a pointer to current node, it becomes intuitive. Always remember: push while going left, pop and visit when you hit null, then move right. Understanding the structure of the tree and edge cases ensures a robust and error-free solution.
- Start with the root node of the binary tree.
- Initialize an empty stack and set the current node as the root.
- While the current node is not null or the stack is not empty, do:
- Push the current node onto the stack and move to its left child until the current node is null.
- When the current node is null, pop a node from the stack, record its value, and set the current node to its right child.
- Repeat until both the current node is null and the stack is empty.
Implementation and efficiency
C implementation
#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
} TreeNode;
TreeNode* createNode(int val) {
TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
node->val = val;
node->left = node->right = NULL;
return node;
}
int* inorderTraversal(TreeNode* root, int* returnSize) {
int* result = malloc(100 * sizeof(int));
TreeNode** stack = malloc(100 * sizeof(TreeNode*));
int top = -1, index = 0;
TreeNode* current = root;
while (current || top >= 0) {
while (current) {
stack[++top] = current;
current = current->left;
}
current = stack[top--];
result[index++] = current->val;
current = current->right;
}
*returnSize = index;
free(stack);
return result;
}
int main() {
TreeNode* root = createNode(1);
root->left = createNode(2);
root->right = createNode(3);
root->left->left = createNode(4);
root->left->right = createNode(5);
int returnSize;
int* res = inorderTraversal(root, &returnSize);
for (int i = 0; i < returnSize; i++) {
printf("%d ", res[i]);
}
printf("\n");
free(res);
return 0;
}C++ implementation
#include <iostream>
#include <stack>
using namespace std;
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
void inorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* current = root;
while (current || !st.empty()) {
while (current) {
st.push(current);
current = current->left;
}
current = st.top();
st.pop();
cout << current->val << " ";
current = current->right;
}
}
int main() {
TreeNode* root = new TreeNode(1);
root->left = new TreeNode(2);
root->right = new TreeNode(3);
root->left->left = new TreeNode(4);
root->left->right = new TreeNode(5);
inorderTraversal(root);
cout << endl;
return 0;
}Python implementation
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def inorderTraversal(root):
result = []
stack = []
current = root
while current or stack:
while current:
stack.append(current)
current = current.left
current = stack.pop()
result.append(current.val)
current = current.right
return result
if __name__ == '__main__':
root = TreeNode(1, TreeNode(2, TreeNode(4), TreeNode(5)), TreeNode(3))
print(inorderTraversal(root))Java implementation
import java.util.*;
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int x) { val = x; }
}
public class IterativeInorderTraversal {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode current = root;
while (current != null || !stack.isEmpty()) {
while (current != null) {
stack.push(current);
current = current.left;
}
current = stack.pop();
result.add(current.val);
current = current.right;
}
return result;
}
public static void main(String[] args) {
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
IterativeInorderTraversal sol = new IterativeInorderTraversal();
System.out.println(sol.inorderTraversal(root));
}
}JavaScript implementation
class TreeNode {
constructor(val, left = null, right = null) {
this.val = val;
this.left = left;
this.right = right;
}
}
function inorderTraversal(root) {
const result = [];
const stack = [];
let current = root;
while (current || stack.length) {
while (current) {
stack.push(current);
current = current.left;
}
current = stack.pop();
result.push(current.val);
current = current.right;
}
return result;
}
const root = new TreeNode(1, new TreeNode(2, new TreeNode(4), new TreeNode(5)), new TreeNode(3));
console.log(inorderTraversal(root));Go implementation
package main
import (
"fmt"
)
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func inorderTraversal(root *TreeNode) []int {
var result []int
stack := []*TreeNode{}
current := root
for current != nil || len(stack) > 0 {
for current != nil {
stack = append(stack, current)
current = current.Left
}
current = stack[len(stack)-1]
stack = stack[:len(stack)-1]
result = append(result, current.Val)
current = current.Right
}
return result
}
func main() {
root := &TreeNode{1, &TreeNode{2, &TreeNode{4, nil, nil}, &TreeNode{5, nil, nil}}, &TreeNode{3, nil, nil}}
fmt.Println(inorderTraversal(root))
}Rust implementation
use std::rc::Rc;
use std::cell::RefCell;
#[derive(Debug)]
struct TreeNode {
val: i32,
left: Option<Rc<RefCell<TreeNode>>>,
right: Option<Rc<RefCell<TreeNode>>>,
}
fn inorder_traversal(root: Option<Rc<RefCell<TreeNode>>>) -> Vec<i32> {
let mut result = vec![];
let mut stack = vec![];
let mut current = root;
while current.is_some() || !stack.is_empty() {
while let Some(node) = current {
stack.push(Rc::clone(&node));
current = node.borrow().left.clone();
}
current = stack.pop();
if let Some(node) = current {
result.push(node.borrow().val);
current = node.borrow().right.clone();
}
}
result
}
fn main() {
let root = Some(Rc::new(RefCell::new(TreeNode {
val: 1,
left: Some(Rc::new(RefCell::new(TreeNode {
val: 2,
left: Some(Rc::new(RefCell::new(TreeNode { val: 4, left: None, right: None }))),
right: Some(Rc::new(RefCell::new(TreeNode { val: 5, left: None, right: None }))),
}))),
right: Some(Rc::new(RefCell::new(TreeNode { val: 3, left: None, right: None }))),
})));
println!("{:?}", inorder_traversal(root));
}Kotlin implementation
class TreeNode(var `val`: Int) {
var left: TreeNode? = null
var right: TreeNode? = null
}
fun inorderTraversal(root: TreeNode?): List<Int> {
val result = mutableListOf<Int>()
val stack = ArrayDeque<TreeNode>()
var current = root
while (current != null || stack.isNotEmpty()) {
while (current != null) {
stack.addFirst(current)
current = current.left
}
current = stack.removeFirst()
result.add(current.`val`)
current = current.right
}
return result
}
fun main() {
val root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left!!.left = TreeNode(4)
root.left!!.right = TreeNode(5)
println(inorderTraversal(root))
}Swift implementation
class TreeNode {
var val: Int
var left: TreeNode?
var right: TreeNode?
init(_ val: Int) {
self.val = val
self.left = nil
self.right = nil
}
}
func inorderTraversal(_ root: TreeNode?) -> [Int] {
var result = [Int]()
var stack = [TreeNode]()
var current = root
while current != nil || !stack.isEmpty {
while let node = current {
stack.append(node)
current = node.left
}
current = stack.removeLast()
if let node = current {
result.append(node.val)
current = node.right
}
}
return result
}
let root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left!.left = TreeNode(4)
root.left!.right = TreeNode(5)
print(inorderTraversal(root))TypeScript implementation
class TreeNode {
val: number;
left: TreeNode | null;
right: TreeNode | null;
constructor(val: number, left: TreeNode | null = null, right: TreeNode | null = null) {
this.val = val;
this.left = left;
this.right = right;
}
}
function inorderTraversal(root: TreeNode | null): number[] {
const result: number[] = [];
const stack: TreeNode[] = [];
let current: TreeNode | null = root;
while (current || stack.length > 0) {
while (current) {
stack.push(current);
current = current.left;
}
current = stack.pop()!;
result.push(current.val);
current = current.right;
}
return result;
}
const root = new TreeNode(1, new TreeNode(2, new TreeNode(4), new TreeNode(5)), new TreeNode(3));
console.log(inorderTraversal(root));