Postorder traversal of Binary Tree without recursion and without stack (original) (raw)

Last Updated : 31 Mar, 2023

Given a binary tree, perform postorder traversal.

Prerequisite - Inorder/preorder/postorder traversal of tree

We have discussed the below methods for postorder traversal.

  1. Recursive Postorder Traversal.
  2. Postorder traversal using Stack.
  3. Postorder traversal using two Stacks.

Approach 1

The approach used is based on using an unordered set to keep track of visited nodes and a while loop to traverse the tree. The steps involved in the approach can be expressed mathematically as follows:

Algorithm

Define a struct Node with integer data, pointer to left child and pointer to right child. Define a helper function called "postorder" which takes a pointer to the head of the tree. Create a pointer "temp" and an unordered set "visited". While "temp" is not NULL and "temp" is not visited before: a. If "temp" has a left child and the left child is not visited before, then set "temp" to its left child and continue the loop. b. If "temp" does not have a left child or the left child is already visited, check if "temp" has a right child and the right child is not visited before. If yes, set "temp" to its right child and continue the loop. c. If "temp" does not have a left child or the left child is already visited, and "temp" does not have a right child or the right child is already visited, then print the data of "temp", insert "temp" into "visited" set, and set "temp" to the head of the tree. Define a function called "newNode" which takes an integer data as input and returns a new Node with the given data, NULL left pointer, and NULL right pointer.

C++ `

// CPP program or postorder traversal #include <bits/stdc++.h> using namespace std;

/* A binary tree node has data, pointer to left child and a pointer to right child */ struct Node { int data; struct Node *left, *right; };

/* Helper function that allocates a new node with the given data and NULL left and right pointers. / void postorder(struct Node head) { struct Node* temp = head; unordered_set<Node*> visited; while (temp && visited.find(temp) == visited.end()) {

    // Visited left subtree
    if (temp->left && 
     visited.find(temp->left) == visited.end())
        temp = temp->left;

    // Visited right subtree
    else if (temp->right && 
    visited.find(temp->right) == visited.end())
        temp = temp->right;

    // Print node
    else {
        printf("%d ", temp->data);
        visited.insert(temp);
        temp = head;
    }
}

}

struct Node* newNode(int data) { struct Node* node = new Node; node->data = data; node->left = NULL; node->right = NULL; return (node); }

/* Driver program to test above functions*/ int main() { struct Node* root = newNode(8); root->left = newNode(3); root->right = newNode(10); root->left->left = newNode(1); root->left->right = newNode(6); root->left->right->left = newNode(4); root->left->right->right = newNode(7); root->right->right = newNode(14); root->right->right->left = newNode(13); postorder(root); return 0; }

Java

// JAVA program or postorder traversal import java.util.*;

/* A binary tree node has data, pointer to left child and a pointer to right child */ class Node { int data; Node left, right; Node(int data) { this.data = data; this.left = this.right = null;
} };

class GFG {

Node root;

/* Helper function that allocates a new node with the given data and null left and right pointers. */ void postorder(Node head) { Node temp = root;
HashSet visited = new HashSet<>(); while ((temp != null && !visited.contains(temp))) {

    // Visited left subtree
    if (temp.left != null && 
     !visited.contains(temp.left))
        temp = temp.left;

    // Visited right subtree
    else if (temp.right != null && 
    !visited.contains(temp.right))
        temp = temp.right;

    // Print node
    else 
    {
        System.out.printf("%d ", temp.data);
        visited.add(temp);
        temp = head;
    }
}

}

/* Driver program to test above functions*/ public static void main(String[] args) { GFG gfg = new GFG(); gfg.root = new Node(8); gfg.root.left = new Node(3); gfg.root.right = new Node(10); gfg.root.left.left = new Node(1); gfg.root.left.right = new Node(6); gfg.root.left.right.left = new Node(4); gfg.root.left.right.right = new Node(7); gfg.root.right.right = new Node(14); gfg.root.right.right.left = new Node(13); gfg.postorder(gfg.root); } }

// This code is contributed by Rajput-Ji

Python

Python program or postorder traversal

''' A binary tree node has data, pointer to left child and a pointer to right child ''' class newNode:

# Constructor to create a newNode 
def __init__(self, data): 
    self.data = data 
    self.left = None
    self.right = None

''' Helper function that allocates a new node with the given data and NULL left and right pointers. ''' def postorder(head):

temp = head 
visited = set()
while (temp and temp not in visited): 
    
    # Visited left subtree 
    if (temp.left and temp.left not in visited):
        temp = temp.left 
        
    # Visited right subtree 
    elif (temp.right and temp.right not in visited):
        temp = temp.right 
    
    # Print node 
    else:
        print(temp.data, end = " ") 
        visited.add(temp) 
        temp = head 

''' Driver program to test above functions''' if name == 'main':

root = newNode(8) 
root.left = newNode(3) 
root.right = newNode(10) 
root.left.left = newNode(1) 
root.left.right = newNode(6) 
root.left.right.left = newNode(4) 
root.left.right.right = newNode(7) 
root.right.right = newNode(14) 
root.right.right.left = newNode(13) 
postorder(root) 

This code is contributed by

SHUBHAMSINGH10

C#

// C# program or postorder traversal using System; using System.Collections.Generic;

/* A binary tree node has data, pointer to left child and a pointer to right child */ public class Node { public int data; public Node left, right; public Node(int data) { this.data = data; this.left = this.right = null;
} };

class GFG {

Node root;

/* Helper function that allocates a new node with the given data and null left and right pointers. */ void postorder(Node head) { Node temp = root;
HashSet visited = new HashSet(); while ((temp != null && !visited.Contains(temp))) {

  // Visited left subtree
  if (temp.left != null && 
      !visited.Contains(temp.left))
    temp = temp.left;

  // Visited right subtree
  else if (temp.right != null && 
           !visited.Contains(temp.right))
    temp = temp.right;

  // Print node
  else 
  {
    Console.Write(temp.data + " ");
    visited.Add(temp);
    temp = head;
  }
}

}

/* Driver code*/ public static void Main(String[] args) { GFG gfg = new GFG(); gfg.root = new Node(8); gfg.root.left = new Node(3); gfg.root.right = new Node(10); gfg.root.left.left = new Node(1); gfg.root.left.right = new Node(6); gfg.root.left.right.left = new Node(4); gfg.root.left.right.right = new Node(7); gfg.root.right.right = new Node(14); gfg.root.right.right.left = new Node(13); gfg.postorder(gfg.root); } }

// This code is contributed by Rajput-Ji

JavaScript

`

Output:

1 4 7 6 3 13 14 10 8

Time complexity: O(N) where N is no of nodes in a binary tree

Auxiliary Space: O(n) since using unordered_set

Alternate Solution:

We can keep the visited flag with every node instead of a separate hash table.

C++ `

// CPP program or postorder traversal #include <bits/stdc++.h> using namespace std;

/* A binary tree node has data, pointer to left child and a pointer to right child */ struct Node { int data; struct Node *left, *right; bool visited; };

void postorder(struct Node* head) { struct Node* temp = head; while (temp && temp->visited == false) {

    // Visited left subtree
    if (temp->left && temp->left->visited == false)
        temp = temp->left;

    // Visited right subtree
    else if (temp->right && temp->right->visited == false)
        temp = temp->right;

    // Print node
    else {
        printf("%d ", temp->data);
        temp->visited = true;
        temp = head;
    }
}

}

struct Node* newNode(int data) { struct Node* node = new Node; node->data = data; node->left = NULL; node->right = NULL; node->visited = false; return (node); }

/* Driver program to test above functions*/ int main() { struct Node* root = newNode(8); root->left = newNode(3); root->right = newNode(10); root->left->left = newNode(1); root->left->right = newNode(6); root->left->right->left = newNode(4); root->left->right->right = newNode(7); root->right->right = newNode(14); root->right->right->left = newNode(13); postorder(root); return 0; }

Java

// Java program or postorder traversal class GFG {

/* A binary tree node has data, pointer to left child and a pointer to right child */ static class Node { int data; Node left, right; boolean visited; }

static void postorder( Node head) { Node temp = head; while (temp != null && temp.visited == false) {

    // Visited left subtree
    if (temp.left != null && 
        temp.left.visited == false)
        temp = temp.left;

    // Visited right subtree
    else if (temp.right != null && 
            temp.right.visited == false)
        temp = temp.right;

    // Print node
    else 
    {
        System.out.printf("%d ", temp.data);
        temp.visited = true;
        temp = head;
    }
}

}

static Node newNode(int data) { Node node = new Node(); node.data = data; node.left = null; node.right = null; node.visited = false; return (node); }

/* Driver code*/ public static void main(String []args) { Node root = newNode(8); root.left = newNode(3); root.right = newNode(10); root.left.left = newNode(1); root.left.right = newNode(6); root.left.right.left = newNode(4); root.left.right.right = newNode(7); root.right.right = newNode(14); root.right.right.left = newNode(13); postorder(root); } }

// This code is contributed by Arnab Kundu

Python3

"""Python3 program or postorder traversal """

A Binary Tree Node

Utility function to create a

new tree node

class newNode:

# Constructor to create a newNode 
def __init__(self, data): 
    self.data = data 
    self.left = None
    self.right = None
    self.visited = False

def postorder(head) :

temp = head 
while (temp and temp.visited == False):

    # Visited left subtree 
    if (temp.left and 
        temp.left.visited == False):
        temp = temp.left 

    # Visited right subtree 
    elif (temp.right and 
          temp.right.visited == False): 
        temp = temp.right 

    # Print node 
    else:
        print(temp.data, end = " ") 
        temp.visited = True
        temp = head
                    

Driver Code

if name == 'main':

root = newNode(8) 
root.left = newNode(3) 
root.right = newNode(10) 
root.left.left = newNode(1) 
root.left.right = newNode(6) 
root.left.right.left = newNode(4) 
root.left.right.right = newNode(7) 
root.right.right = newNode(14) 
root.right.right.left = newNode(13) 
postorder(root)

This code is contributed by

SHUBHAMSINGH10

C#

// C# program or postorder traversal using System;

class GFG {

/* A binary tree node has data, pointer to left child and a pointer to right child */ class Node { public int data; public Node left, right; public bool visited; }

static void postorder( Node head) { Node temp = head; while (temp != null && temp.visited == false) {

    // Visited left subtree
    if (temp.left != null && 
        temp.left.visited == false)
        temp = temp.left;

    // Visited right subtree
    else if (temp.right != null && 
            temp.right.visited == false)
        temp = temp.right;

    // Print node
    else
    {
        Console.Write("{0} ", temp.data);
        temp.visited = true;
        temp = head;
    }
}

}

static Node newNode(int data) { Node node = new Node(); node.data = data; node.left = null; node.right = null; node.visited = false; return (node); }

/* Driver code*/ public static void Main(String []args) { Node root = newNode(8); root.left = newNode(3); root.right = newNode(10); root.left.left = newNode(1); root.left.right = newNode(6); root.left.right.left = newNode(4); root.left.right.right = newNode(7); root.right.right = newNode(14); root.right.right.left = newNode(13); postorder(root); } }

// This code is contributed by 29AjayKumar

JavaScript

`

Output:

1 4 7 6 3 13 14 10 8

Time complexity: O(n2) in worst case we move pointer back to head after visiting every node.

Auxiliary Space: O(1)

Alternate solution using unordered_map in which we do not have to move pointer back to head, so time complexity is O(n).

C++ `

// CPP program or postorder traversal #include <bits/stdc++.h> using namespace std;

/* A binary tree node has data, pointer to left child and a pointer to right child */ struct Node { int data; struct Node *left, *right; bool visited; };

void postorder(Node* root) { Node* n = root; unordered_map<Node*, Node*> parentMap; parentMap.insert(pair<Node*, Node*>(root, nullptr));

while (n) {
    if (n->left && parentMap.find(n->left) == parentMap.end()) {
        parentMap.insert(pair<Node*, Node*>(n->left, n));
        n = n->left;
    }
    else if (n->right && parentMap.find(n->right) == parentMap.end()) {
        parentMap.insert(pair<Node*, Node*>(n->right, n));
        n = n->right;
    }
    else {
        cout << n->data << " ";
        n = (parentMap.find(n))->second;
    }
}

} struct Node* newNode(int data) { struct Node* node = new Node; node->data = data; node->left = NULL; node->right = NULL; node->visited = false; return (node); }

/* Driver program to test above functions*/ int main() { struct Node* root = newNode(8); root->left = newNode(3); root->right = newNode(10); root->left->left = newNode(1); root->left->right = newNode(6); root->left->right->left = newNode(4); root->left->right->right = newNode(7); root->right->right = newNode(14); root->right->right->left = newNode(13); postorder(root); return 0; }

Java

import java.util.HashMap; import java.util.Map;

class Node { int data; Node left, right; boolean visited; }

public class Tree { static Map<Node, Node> parentMap = new HashMap<>();

static void postorder(Node root) {
    Node n = root;
    parentMap.put(root, null);

    while (n != null) {
        if (n.left != null && !parentMap.containsKey(n.left)) {
            parentMap.put(n.left, n);
            n = n.left;
        } else if (n.right != null && !parentMap.containsKey(n.right)) {
            parentMap.put(n.right, n);
            n = n.right;
        } else {
            System.out.print(n.data + " ");
            n = parentMap.get(n);
        }
    }
}

static Node newNode(int data) {
    Node node = new Node();
    node.data = data;
    node.left = null;
    node.right = null;
    node.visited = false;
    return node;
}

public static void main(String[] args) {
    Node root = newNode(8);
    root.left = newNode(3);
    root.right = newNode(10);
    root.left.left = newNode(1);
    root.left.right = newNode(6);
    root.left.right.left = newNode(4);
    root.left.right.right = newNode(7);
    root.right.right = newNode(14);
    root.right.right.left = newNode(13);
    postorder(root);
}

}

Python3

Python3 code for the above approach

A binary tree node class

class Node: def init(self, data): self.data = data self.left = None self.right = None self.visited = False

def postorder(root): n = root parent_map = {} parent_map[root] = None

while n:
    if n.left and n.left not in parent_map:
        parent_map[n.left] = n
        n = n.left
    elif n.right and n.right not in parent_map:
        parent_map[n.right] = n
        n = n.right
    else:
        print(n.data, end = " ")
        n = parent_map[n]

Driver code

if name == 'main': root = Node(8) root.left = Node(3) root.right = Node(10) root.left.left = Node(1) root.left.right = Node(6) root.left.right.left = Node(4) root.left.right.right = Node(7) root.right.right = Node(14) root.right.right.left = Node(13) postorder(root)

C#

// C# program or postorder traversal using System; using System.Collections.Generic;

/* A binary tree node has data, pointer to left child and a pointer to right child */ class Node { public int data; public Node left, right; public bool visited; }

class Tree { static Dictionary<Node, Node> parentMap = new Dictionary<Node, Node>();

static void postorder(Node root) { Node n = root; parentMap[root] = null;

while (n != null) {
  if (n.left != null && !parentMap.ContainsKey(n.left)) {
    parentMap[n.left] = n;
    n = n.left;
  } else if (n.right != null && !parentMap.ContainsKey(n.right)) {
    parentMap[n.right] = n;
    n = n.right;
  } else {
    Console.Write(n.data + " ");
    n = parentMap[n];
  }
}

}

static Node newNode(int data) { Node node = new Node(); node.data = data; node.left = null; node.right = null; node.visited = false; return node; }

static void Main(string[] args) { Node root = newNode(8); root.left = newNode(3); root.right = newNode(10); root.left.left = newNode(1); root.left.right = newNode(6); root.left.right.left = newNode(4); root.left.right.right = newNode(7); root.right.right = newNode(14); root.right.right.left = newNode(13); postorder(root); } }

JavaScript

class Node { constructor(data) { this.data = data; this.left = null; this.right = null; this.visited = false; } }

function postorder(root) { let n = root; const parentMap = new Map(); parentMap.set(root, null);

while (n) { if (n.left && !parentMap.has(n.left)) { parentMap.set(n.left, n); n = n.left; } else if (n.right && !parentMap.has(n.right)) { parentMap.set(n.right, n); n = n.right; } else { console.log(n.data + " "); n = parentMap.get(n); } } }

// Test const root = new Node(8); root.left = new Node(3); root.right = new Node(10); root.left.left = new Node(1); root.left.right = new Node(6); root.left.right.left = new Node(4); root.left.right.right = new Node(7); root.right.right = new Node(14); root.right.right.left = new Node(13); postorder(root);

// This code is contributed by divyansh2212

`

Output:

1 4 7 6 3 13 14 10 8

Time complexity: O(n) where n is no of nodes in a binary tree

Auxiliary Space: O(n) since using unordered_map