Iterative Postorder Traversal

Last Updated : 24 Oct, 2026

Given a binary tree root[]. Find the postorder traversal of the tree without using recursion. Return a list containing the postorder traversal of the tree, calculated without using recursion.

Examples:

Input:


Output: 4 5 2 3 1
Explanation: Postorder traversal (Left->Right->Root) of the tree is 4 5 2 3 1.

Input:

blobid3_1787057141


Output: 10 7 1 6 10 6 5 8 
Explanation: Postorder traversal (Left->Right->Root) of the tree is 10 7 1 6 10 6 5 8.

Try It Yourself
redirect icon

Illustration of Postorder Traversal for Reference

[Two Stacks] Storing Reverse Postorder - O(n) Time and O(n) Space

The idea is to push Reverse Postorder to a stack. Once we have the reversed postorder in a stack, we just pop all items one by one from the stack and print them

How to get reversed postorder in a stack - the second stack is used for this purpose. For example, in the following tree, we need to get reverse of 1 3 2 5 4 (reverse of 4 5 2 3 1) in a stack.

blobid2_1787057141

If we take a closer look at reverse of postorder, we can observe that this sequence is very similar to the preorder traversal. The only difference is that the right child is visited before left child, and therefore the sequence is “root right left” instead of “root left right”. So, we do something like iterative preorder traversal with the following differences:

  • Instead of printing an item, we push it to a stack.
  • We push the left subtree before the right subtree..

Step 1: Create two empty stacks, stack1 and stack2.

  • Push the root into stack1.

Step 2: Process nodes using stack1.

  • Pop a node from stack1 and push it into stack2.
  • Push its left child and then its right child into stack1.

Step 3: Continue until stack1 becomes empty.

  • Each node is processed once and stored in stack2.
  • This gives stack2 the order Root → Right → Left.

Step 4: Process stack2.

  • Pop each node and add its value to the result.
  • Since stack2 follows LIFO, the order becomes Left → Right → Root.

Step 5: The result is the required postorder traversal.

Let us consider the following tree :

blobid2_1787057141

Step 1: Start with stack1 = [1] and stack2 = [].

  • Pop 1 from stack1 and push it into stack2.
  • Push left child 2, then right child 3 into stack1.
  • stack1: [2, 3] | stack2: [1]

Step 2: Process node 3.

  • Pop 3 from stack1 and push it into stack2.
  • 3 has no children.
  • stack1: [2] | stack2: [1, 3]

Step 3: Process node 2.

  • Pop 2 from stack1 and push it into stack2.
  • Push left child 4, then right child 5 into stack1.
  • stack1: [4, 5] | stack2: [1, 3, 2]

Step 4: Process node 5.

  • Pop 5 from stack1 and push it into stack2.
  • 5 has no children.
  • stack1: [4] | stack2: [1, 3, 2, 5]

Step 5: Process node 4.

  • Pop 4 from stack1 and push it into stack2.
  • 4 has no children.
  • stack1: [] | stack2: [1, 3, 2, 5, 4]

Step 6: Now stack1 is empty, so process stack2.

  • Pop nodes from stack2: 4 → 5 → 2 → 3 → 1.
  • Result: 4 5 2 3 1

Final Postorder : 4 5 2 3 1

C++
// C++ program to o find the postorder 
// traversal using 2 Stacks
#include <bits/stdc++.h>
using namespace std;

class Node {
public:
    int data;
    Node* left;
    Node* right;

    Node(int x) {
        data = x;
        left = right = nullptr;
    }
};

// Function to do post-order traversal
// using two stacks iteratively
vector<int> postOrder(Node* root) {
    vector<int> result;
    if (root == nullptr) {
        return result;
    }

    // Create two stacks
    stack<Node*> stk1, stk2;

    // Push root to first stack
    stk1.push(root);
    Node* curr;

    // Run while first stack is not empty
    while (!stk1.empty()) {
      
        // Pop from s1 and push it to s2
        curr = stk1.top();
        stk1.pop();
        stk2.push(curr);

        // Push left and right children of the
        // popped node
        if (curr->left) {
            stk1.push(curr->left);
        }
        if (curr->right) {
            stk1.push(curr->right);
        }
    }

    // Collect all elements from second stack
    while (!stk2.empty()) {
        curr = stk2.top();
        stk2.pop();
        result.push_back(curr->data);
    }

    return result;
}

void printArray(const vector<int>& arr) {
    for (int data : arr) {
        cout << data << " ";
    }
    cout << endl;
}

int main() {
  
    // Representation of input binary tree:
    //           1
    //         /   \
    //        2     3
    //      /  \
    //     4    5
    Node* root = new Node(1);
    root->left = new Node(2);
    root->right = new Node(3);
    root->left->left = new Node(4);
    root->left->right = new Node(5);

    vector<int> result = postOrder(root);

    printArray(result);

    return 0;
}
Java
// Java program to o find the postorder 
// traversal using 2 Stacks
import java.util.ArrayList;
import java.util.Stack;

class Node {
    int data;
    Node left, right;

    Node(int x) {
        data = x;
        left = right = null;
    }
}

class GfG {

    // Function to do post-order traversal 
    // using two stacks
    static ArrayList<Integer> postOrder(Node root) {
        ArrayList<Integer> result = new ArrayList<>();
        if (root == null) {
            return result;
        }

        // Create two stacks
        Stack<Node> stk1 = new Stack<>();
        Stack<Node> stk2 = new Stack<>();

        // Push root to first stack
        stk1.push(root);
        Node curr;

        // Run while first stack is not empty
        while (!stk1.isEmpty()) {

            // Pop from stk1 and push it to stk2
            curr = stk1.pop();
            stk2.push(curr);

            // Push left and right children of 
            // the popped node
            if (curr.left != null) {
                stk1.push(curr.left);
            }
            if (curr.right != null) {
                stk1.push(curr.right);
            }
        }

        // Collect all elements from second stack
        while (!stk2.isEmpty()) {
            curr = stk2.pop();
            result.add(curr.data);
        }

        return result;
    }

    static void printArray(ArrayList<Integer> arr) {
        for (int data : arr) {
            System.out.print(data + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {

        // Representation of input binary tree:
        //           1
        //         /   \
        //        2     3
        //      /  \
        //     4    5
        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);

        ArrayList<Integer> result = postOrder(root);

        printArray(result);
    }
}
Python
# Python program to o find the postorder 
# traversal using 2 Stacks
class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None

# Function to do post-order traversal 
# using two stacks
def postOrder(root):
    result = []
    if root is None:
        return result

    # Create two stacks
    stk1 = []
    stk2 = []

    # Push root to first stack
    stk1.append(root)

    # Run while first stack is not empty
    while stk1:
      
        # Pop from stk1 and push it to stk2
        curr = stk1.pop()
        stk2.append(curr)

        # Push left and right children of 
        # the popped node
        if curr.left:
            stk1.append(curr.left)
        if curr.right:
            stk1.append(curr.right)

    # Collect all elements from second stack
    while stk2:
        curr = stk2.pop()
        result.append(curr.data)

    return result

def printArray(arr):
    print(" ".join(map(str, arr)))

if __name__ == "__main__":
    
    # Representation of input binary tree:
    #           1
    #         /   \
    #        2     3
    #      /  \
    #     4    5
    root = Node(1)
    root.left = Node(2)
    root.right = Node(3)
    root.left.left = Node(4)
    root.left.right = Node(5)

    result = postOrder(root)
    printArray(result)
C#
// C# program to o find the postorder 
// traversal using 2 Stacks
using System;
using System.Collections.Generic;

class Node {
    public int data;
    public Node left, right;

    public Node(int x) {
        data = x;
        left = right = null;
    }
}

class GfG {
    
    // Function to do post-order traversal 
    // using two stacks
    static List<int> postOrder(Node root) {
        List<int> result = new List<int>();
        if (root == null) {
            return result;
        }

        // Create two stacks
        Stack<Node> stk1 = new Stack<Node>();
        Stack<Node> stk2 = new Stack<Node>();

        // Push root to first stack
        stk1.Push(root);

        // Run while first stack is not empty
        while (stk1.Count > 0) {
          
            // Pop from stk1 and push it to stk2
            Node curr = stk1.Pop();
            stk2.Push(curr);

            // Push left and right children of 
            // the popped node
            if (curr.left != null) {
                stk1.Push(curr.left);
            }
            if (curr.right != null) {
                stk1.Push(curr.right);
            }
        }

        // Collect all elements from second stack
        while (stk2.Count > 0) {
            Node curr = stk2.Pop();
            result.Add(curr.data);
        }

        return result;
    }

    static void printArray(List<int> arr) {
        foreach (int data in arr) {
            Console.Write(data + " ");
        }
        Console.WriteLine();
    }

    static void Main(string[] args) {

        // Representation of input binary tree:
        //           1
        //         /   \
        //        2     3
        //      /  \
        //     4    5
        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);

        List<int> result = postOrder(root);
        printArray(result);
    }
}
JavaScript
// JavaScript program to find the postorder 
// traversal using 2 Stacks
class Node {
    constructor(key) {
        this.key = key;
        this.left = null;
        this.right = null;
    }
}

// Function to perform postorder traversal 
// using two stacks
function postOrder(root) {
    const ans = [];
    if (!root) return ans;

    const stk1 = [root];  
    const stk2 = [];     

    // Loop while stk1 is not empty
    while (stk1.length > 0) {
        const node = stk1.pop();
        
         // Push node's key to stk2
        stk2.push(node.key); 

        // Push left and right children to stk1
        if (node.left) stk1.push(node.left);
        if (node.right) stk1.push(node.right);
    }

    // Collect nodes from s2 in postorder
    while (stk2.length > 0) {
        ans.push(stk2.pop());
    }

    return ans;
}

// Representation of input binary tree:
//           1
//         /   \
//        2     3
//      /  \
//     4    5

const root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);

const result = postOrder(root);
console.log(result.join(' '));

Output
4 5 2 3 1 

[Single Stack] Moving both Root and Right - O(n) Time and O(h) Space

The idea is to move down to leftmost node using left pointer. While moving down, push root and root's right child to stack. Once we reach leftmost node, print it if it doesn't have a right child. If it has a right child, then change root so that the right child is processed before. 

Step 1: Create an empty stack.

Step 2: Go to the leftmost node.

  • If the current node has a right child, push the right child into the stack.
  • Push the current node into the stack.
  • Move to the left child.

Step 3: When there is no left child, pop a node from the stack.

  • If its right child is still waiting on the stack, process the right subtree first.
  • Otherwise, add the node to the result.

Step 4: Repeat until the stack is empty.

Let us consider the following tree :

blobid2_1787057141


Step 1: Start at 1.

  • Push its right child 3, then 1.
  • Move to left child 2.
  • Stack: 3, 1

Step 2: At 2.

  • Push its right child 5, then 2.
  • Move to left child 4.
  • Stack: 3, 1, 5, 2

Step 3: At 4.

  • Push 4 and move to NULL.
  • Pop 4 and add it to the result.
  • Result: 4
  • Stack: 3, 1, 5, 2

Step 4: Pop 2.

  • Its right child 5 is waiting on top, so process the right subtree.
  • Remove 5, push 2 back, and move to 5.
  • Process 5 and add it to the result.
  • Result: 4, 5
  • Stack: 3, 1, 2

Step 5: Pop 2 again.

  • Its right subtree is already processed, so add 2.
  • Result: 4, 5, 2
  • Now pop 1.
  • Its right child 3 is waiting, so process 3.
  • Result: 4, 5, 2, 3

Step 6: Pop 1.

  • Both subtrees are processed, so add 1.
  • Result: 4, 5, 2, 3, 1

Final Postorder : 4 5 2 3 1

C++
#include <bits/stdc++.h>
using namespace std;

class Node {
public:
    int data;
    Node* left;
    Node* right;

    Node(int x) {
        data = x;
        left = right = nullptr;
    }
};

vector<int> postOrder(Node* root) {
    vector<int> result;
    if (root == nullptr)
        return result;

    stack<Node*> stk;

    while (root != nullptr || !stk.empty()) {
        while (root != nullptr) {
            if (root->right != nullptr)
                stk.push(root->right);

            stk.push(root);
            root = root->left;
        }

        root = stk.top();
        stk.pop();

        if (!stk.empty() && root->right != nullptr &&
            stk.top() == root->right) {

            stk.pop();
            stk.push(root);
            root = root->right;
        }
        else {
            result.push_back(root->data);
            root = nullptr;
        }
    }

    return result;
}

int main() {
    Node* root = new Node(1);

    root->left = new Node(2);
    root->right = new Node(3);
    root->left->left = new Node(4);
    root->left->right = new Node(5);

    vector<int> result = postOrder(root);

    for (int x : result)
        cout << x << " ";

    return 0;
}
C
#include <stdio.h>
#include <stdlib.h>

struct Node {
    int data;
    struct Node* left;
    struct Node* right;
};

struct Node* createNode(int x) {
    struct Node* node = (struct Node*)malloc(sizeof(struct Node));
    node->data = x;
    node->left = node->right = NULL;
    return node;
}

void postOrder(struct Node* root) {
    struct Node* stk[100];
    int top = -1;

    while (root != NULL || top >= 0) {
        while (root != NULL) {
            if (root->right != NULL)
                stk[++top] = root->right;

            stk[++top] = root;
            root = root->left;
        }

        root = stk[top--];

        if (top >= 0 && root->right != NULL &&
            stk[top] == root->right) {

            top--;
            stk[++top] = root;
            root = root->right;
        }
        else {
            printf("%d ", root->data);
            root = NULL;
        }
    }
}

int main() {
    struct Node* root = createNode(1);

    root->left = createNode(2);
    root->right = createNode(3);
    root->left->left = createNode(4);
    root->left->right = createNode(5);

    postOrder(root);

    return 0;
}
Java
import java.util.ArrayList;
import java.util.Stack;

class Node {
    int data;
    Node left, right;

    Node(int x) {
        data = x;
        left = right = null;
    }
}

class GfG {

    static ArrayList<Integer> postOrder(Node root) {
        ArrayList<Integer> result = new ArrayList<>();
        if (root == null)
            return result;

        Stack<Node> stk = new Stack<>();

        while (root != null || !stk.isEmpty()) {
            while (root != null) {
                if (root.right != null)
                    stk.push(root.right);

                stk.push(root);
                root = root.left;
            }

            root = stk.pop();

            if (!stk.isEmpty() && root.right != null &&
                stk.peek() == root.right) {

                stk.pop();
                stk.push(root);
                root = root.right;
            }
            else {
                result.add(root.data);
                root = null;
            }
        }

        return result;
    }

    public static void main(String[] args) {
        Node root = new Node(1);

        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);

        ArrayList<Integer> result = postOrder(root);

        for (int x : result)
            System.out.print(x + " ");
    }
}
Python
class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None


def postOrder(root):
    result = []

    if root is None:
        return result

    stk = []

    while root is not None or stk:
        while root is not None:
            if root.right is not None:
                stk.append(root.right)

            stk.append(root)
            root = root.left

        root = stk.pop()

        if stk and root.right is not None and stk[-1] == root.right:
            stk.pop()
            stk.append(root)
            root = root.right
        else:
            result.append(root.data)
            root = None

    return result


if __name__ == "__main__":
    root = Node(1)

    root.left = Node(2)
    root.right = Node(3)
    root.left.left = Node(4)
    root.left.right = Node(5)

    result = postOrder(root)

    print(*result)
C#
using System;
using System.Collections.Generic;

class Node {
    public int data;
    public Node left, right;

    public Node(int x) {
        data = x;
        left = right = null;
    }
}

class GfG {

    static List<int> postOrder(Node root) {
        List<int> result = new List<int>();

        if (root == null)
            return result;

        Stack<Node> stk = new Stack<Node>();

        while (root != null || stk.Count > 0) {
            while (root != null) {
                if (root.right != null)
                    stk.Push(root.right);

                stk.Push(root);
                root = root.left;
            }

            root = stk.Pop();

            if (stk.Count > 0 && root.right != null &&
                stk.Peek() == root.right) {

                stk.Pop();
                stk.Push(root);
                root = root.right;
            }
            else {
                result.Add(root.data);
                root = null;
            }
        }

        return result;
    }

    public static void Main() {
        Node root = new Node(1);

        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);

        List<int> result = postOrder(root);

        foreach (int x in result)
            Console.Write(x + " ");
    }
}

Output
4 5 2 3 1 

[Single Stack] Tracking Last Visited Node - O(n) Time and O(n) Space

Use one stack to simulate recursion. Move left while pushing nodes onto the stack. When the left subtree is done, check the top node’s right child. If it is not visited, process the right subtree; otherwise, process the node itself.

Step 1: Create an empty stack and set lastVisited as NULL.

Step 2: Go to the leftmost node.

  • Push the current node into the stack.
  • Move to the left child.
  • Repeat until the current node becomes NULL.

Step 3: When the current node is NULL, check the top node of the stack.

  • If it has a right child that has not been visited, move to the right child.
  • Otherwise, add the node to the result, mark it as lastVisited, and pop it from the stack.

Step 4: Repeat the above steps until both the stack is empty and the current node is NULL.

Step 5: The result gives the nodes in Left -> Right -> Root order, which is the postorder traversal.

Let us consider the following tree :

blobid2_1787057141


Step 1: Start with an empty stack and lastVisited = NULL.

  • Push 1, 2, and 4 while moving to the leftmost node.
  • Current node becomes NULL.
  • Stack: 1, 2, 4

Step 2: Check the top node 4.

  • 4 has no right child, so process 4.
  • Result: 4, lastVisited = 4
  • Stack: 1, 2

Step 3: Check the top node 2.

  • Its right child 5 is not visited, so move to 5.
  • Push 5 and move to NULL.
  • Stack: 1, 2, 5

Step 4: Check the top node 5.

  • 5 has no right child, so process 5.
  • Result: 4, 5, lastVisited = 5
  • Stack: 1, 2

Step 5: Check 2 again.

  • Its right child 5 is already visited, so process 2.
  • Result: 4, 5, 2, lastVisited = 2
  • Stack: 1

Step 6: Check 1.

  • Its right child 3 is not visited, so move to 3 and process it.
  • Result: 4, 5, 2, 3, lastVisited = 3
  • Stack: 1

Step 7: Check 1 again.

  • Its right child 3 is already visited, so process 1.
  • Result: 4, 5, 2, 3, 1
  • Stack: empty.

Final Postorder : 4 5 2 3 1

C++
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <sstream>  
using namespace std;

struct Node {
    int data;
    Node* left;
    Node* right;

    Node(int val) {
        data = val;
        left = nullptr;
        right = nullptr;
    }
};

vector<int> postOrder(Node* root) {
    vector<int> res;
    if (!root) return res;

    stack<Node*> s;
    Node* lastVisited = nullptr;

    while (!s.empty() || root) {
        
        // Keep moving to the left 
        // until we reach a null
        if (root) {
            s.push(root);
            root = root->left;
        }
        else {
            
            // Take out an item from stack
            Node* peekNode = s.top();
            
            // If the taken out item has a 
            // right child and the right child
            // is not visited, move to the right
            if (peekNode->right && lastVisited != peekNode->right) {
                root = peekNode->right;
                
            // If there is no right child
            // or the right child is already
            // visited, then add peekNode to the
            // result and remove from the stack
            } else {
                res.push_back(peekNode->data);
                lastVisited = s.top();
                s.pop();
            }
        }
    }

    return res;
}

// Driver program to test above functions
int main() {
    Node* root = new Node(1);
    root->left = new Node(2);
    root->right = new Node(3);
    root->left->left = new Node(4);
    root->left->right = new Node(5);

    vector<int> res = postOrder(root);
    for (auto it : res)
        cout << it << " ";
    return 0;
}
Java
import java.util.ArrayList;
import java.util.Stack;

class Node {
    int data;
    Node left, right;

    Node(int val) {
        data = val;
        left = null;
        right = null;
    }
}

class GfG {

    static ArrayList<Integer> postOrder(Node root) {
        ArrayList<Integer> res = new ArrayList<>();
        if (root == null) return res;

        Stack<Node> s = new Stack<>();
        Node lastVisited = null;

        while (!s.isEmpty() || root != null) {

            if (root != null) {
                s.push(root);
                root = root.left;
            } else {
                Node peekNode = s.peek();

                if (peekNode.right != null && lastVisited != peekNode.right) {
                    root = peekNode.right;
                } else {
                    res.add(peekNode.data);
                    lastVisited = s.pop();
                }
            }
        }

        return res;
    }

    public static void main(String[] args) {
        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);
    

        ArrayList<Integer> res = postOrder(root);

        for (int x : res)
            System.out.print(x + " ");
    }
}
Python
class Node:
    def __init__(self, val):
        self.data = val
        self.left = None
        self.right = None


def postOrder(root):
    res = []
    if root is None:
        return res

    s = []
    lastVisited = None

    while s or root:
        if root:
            s.append(root)
            root = root.left
        else:
            peekNode = s[-1]
            if peekNode.right and lastVisited != peekNode.right:
                root = peekNode.right
            else:
                res.append(peekNode.data)
                lastVisited = s.pop()

    return res


# Driver program to test above functions
if __name__ == '__main__':
    root = Node(1)
    root.left = Node(2)
    root.right = Node(3)
    root.left.left = Node(4)
    root.left.right = Node(5)
 

    res = postOrder(root)
    print(' '.join(map(str, res)), end='')
   
C#
using System;
using System.Collections.Generic;

class Node {
    public int data;
    public Node left, right;

    public Node(int val) {
        data = val;
        left = right = null;
    }
}

class Program {
    static List<int> PostOrder(Node root) {
        List<int> res = new List<int>();
        if (root == null) return res;

        Stack<Node> s = new Stack<Node>();
        Node lastVisited = null;

        while (s.Count > 0 || root != null) {
            if (root != null) {
                s.Push(root);
                root = root.left;
            } else {
                Node peekNode = s.Peek();
                if (peekNode.right != null && lastVisited != peekNode.right) {
                    root = peekNode.right;
                } else {
                    res.Add(peekNode.data);
                    lastVisited = s.Pop();
                }
            }
        }
        return res;
    }

    static void Main() {
        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);
      

        List<int> res = PostOrder(root);
        Console.Write(string.Join(" ", res));
        
    }
}

Output
4 5 2 3 1 

[Single Stack] Iterative Postorder Traversal - O(n) Time and O(n) Space

The main idea is to simulate the recursive postorder traversal using a stack. Along with each node, we store an extra field that tells us whether the node is being processed for its left child, right child, or itself.

0 : Left child needs to be processed
1 : Right child needs to be processed
2 : Node itself is ready to be added to the postorder traversal

Step 1: Initialize the stack

  • Create a stack that stores pairs of (node, state).
  • If the tree is not empty, push the root node with state 0.

Step 2: Process the top element

  • Pop the top pair (node, state) from the stack.
  • The state tells us what should be processed next for that node.

Step 3: Process according to the state

If state = 0:

  • Push (node, 1) back into the stack.
  • Push the left child as (node->left, 0) if it exists.
  • This ensures that the left subtree is processed before moving to the right subtree.

If state = 1:

  • Push (node, 2) back into the stack.
  • Push the right child as (node->right, 0) if it exists.
  • This ensures that the right subtree is processed before the node itself.

If state = 2:

  • The left and right subtrees have been processed.
  • Add node->data to the result.

Step 4: Repeat

  • Continue processing while the stack is not empty.
  • The nodes are added to the result in the order Left → Right → Root, which is the postorder traversal.

Let us consider the following tree :

blobid2_1787057141


Step 1: Start with the root

  • Push (1, 0) into the stack.
  • State 0 means the left subtree needs to be processed.
  • Stack: [(1, 0)]
  • Result: []

Step 2: Process node 1

  • Pop (1, 0).
  • Push (1, 1) back into the stack.
  • Push its left child (2, 0).
  • Stack: [(1, 1), (2, 0)]
  • Result: []

Step 3: Process node 2 and its left subtree

  • Pop (2, 0).
  • Push (2, 1) and then push its left child (4, 0).
  • Node 4 has no children, so add 4 to the result.
  • Then process the right child of 2 by pushing (2, 2) and (5, 0).
  • Node 5 has no children, so add 5 to the result.
  • Stack: [(1, 1), (2, 2)]
  • Result: [4, 5]

Step 4: Process node 2

  • Pop (2, 2).
  • Both its left and right subtrees are processed.
  • Add 2 to the result.
  • Stack: [(1, 1)]
  • Result: [4, 5, 2]

Step 5: Process node 1's right subtree

  • Pop (1, 1).
  • Push (1, 2) and then push its right child (3, 0).
  • Node 3 has no children, so add 3 to the result.
  • Stack: [(1, 2)]
  • Result: [4, 5, 2, 3]

Step 6: Process node 1

  • Pop (1, 2).
  • Both its left and right subtrees are processed.
  • Add 1 to the result.
  • Stack: []
  • Result: [4, 5, 2, 3, 1]

Therefore, the postorder traversal is [4, 5, 2, 3, 1].

C++
#include <bits/stdc++.h>
using namespace std;

struct Node {
    int data;
    Node* left;
    Node* right;

    Node(int val) {
        data = val;
        left = right = NULL;
    }
};

vector<int> postOrder(Node* root) {
    vector<int> ans;

    if (root == NULL)
        return ans;

    // Stack stores the node along with its current state.
    stack<pair<Node*, int>> st;
    st.push({root, 0});

    while (!st.empty()) {
        auto [node, state] = st.top();
        st.pop();

        // State 0: Process the left subtree.
        if (state == 0) {
            st.push({node, 1});

            if (node->left)
                st.push({node->left, 0});
        }

        // State 1: Process the right subtree.
        else if (state == 1) {
            st.push({node, 2});

            if (node->right)
                st.push({node->right, 0});
        }

        // State 2: Both subtrees are processed, so add the node.
        else {
            ans.push_back(node->data);
        }
    }

    return ans;
}

int main() {
    Node* root = new Node(1);
    root->left = new Node(2);
    root->right = new Node(3);
    root->left->left = new Node(4);
    root->left->right = new Node(5);

    vector<int> ans = postOrder(root);

    for (int x : ans)
        cout << x << " ";

    return 0;
}
Java
import java.util.ArrayList;
import java.util.Stack;

public class GFG {

    static class NodeState {
        Node node;
        int state;

        NodeState(Node node, int state) {
            this.node = node;
            this.state = state;
        }
    }

    static ArrayList<Integer> postOrder(Node root) {
        ArrayList<Integer> ans = new ArrayList<>();

        if (root == null)
            return ans;

        // Stack stores each node along with its current state.
        Stack<NodeState> st = new Stack<>();
        st.push(new NodeState(root, 0));

        while (!st.empty()) {
            NodeState current = st.pop();

            Node node = current.node;
            int state = current.state;

            // State 0: Process the left subtree.
            if (state == 0) {
                st.push(new NodeState(node, 1));

                if (node.left != null)
                    st.push(new NodeState(node.left, 0));
            }

            // State 1: Process the right subtree.
            else if (state == 1) {
                st.push(new NodeState(node, 2));

                if (node.right != null)
                    st.push(new NodeState(node.right, 0));
            }

            // State 2: Both subtrees are processed, so add the node.
            else {
                ans.add(node.data);
            }
        }

        return ans;
    }

    public static void main(String[] args) {
        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);

        ArrayList<Integer> ans = postOrder(root);

        for (int x : ans)
            System.out.print(x + " ");
    }
}
Python
def postOrder(root):
    ans = []

    if root is None:
        return ans

    # Stack stores the node along with its current state.
    stack = [(root, 0)]

    while stack:
        node, state = stack.pop()

        # State 0: Process the left subtree.
        if state == 0:
            stack.append((node, 1))

            if node.left:
                stack.append((node.left, 0))

        # State 1: Process the right subtree.
        elif state == 1:
            stack.append((node, 2))

            if node.right:
                stack.append((node.right, 0))

        # State 2: Both subtrees are processed, so add the node.
        else:
            ans.append(node.data)

    return ans


if __name__ == "__main__":
    root = Node(1)
    root.left = Node(2)
    root.right = Node(3)
    root.left.left = Node(4)
    root.left.right = Node(5)

    print(*postOrder(root))
C#
using System;
using System.Collections.Generic;

class NodeState
{
    public Node node;
    public int state;

    public NodeState(Node node, int state)
    {
        this.node = node;
        this.state = state;
    }
}

public class GFG
{
    static List<int> postOrder(Node root)
    {
        List<int> ans = new List<int>();

        if (root == null)
            return ans;

        // Stack stores the node along with its current state.
        Stack<NodeState> st = new Stack<NodeState>();
        st.Push(new NodeState(root, 0));

        while (st.Count > 0)
        {
            NodeState current = st.Pop();

            Node node = current.node;
            int state = current.state;

            // State 0: Process the left subtree.
            if (state == 0)
            {
                st.Push(new NodeState(node, 1));

                if (node.left != null)
                    st.Push(new NodeState(node.left, 0));
            }

            // State 1: Process the right subtree.
            else if (state == 1)
            {
                st.Push(new NodeState(node, 2));

                if (node.right != null)
                    st.Push(new NodeState(node.right, 0));
            }

            // State 2: Both subtrees are processed, so add the node.
            else
            {
                ans.Add(node.data);
            }
        }

        return ans;
    }

    public static void Main()
    {
        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);

        List<int> ans = postOrder(root);

        foreach (int x in ans)
            Console.Write(x + " ");
    }
}

Output
4 5 2 3 1 


Comment