Open In App

Postorder Traversal of Binary Tree in C++

Last Updated : 30 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Post-order binary tree traversal is a type of depth-first traversal that follows the order of visiting the left subtree, then the right subtree, and finally the node itself. It is useful for operations where you need to work with a node only after you’ve dealt with its children, such as when calculating the size of the tree or deleting the tree.

In this article, we will learn about post-order binary tree traversal in C++, how to implement it in C++ using both recursion and iteration methods and analyze the time and space complexity of both methods.

Post Order Traversal in C++

Consider the following binary search tree for the demonstration:

          8
        /   \
       3     10
     /   \      \
    1     6      14

For post-order traversal of the given tree, we

  • First, descend the left subtree as deep as possible.
  • Then, descend the right subtree as deep as possible.
  • Finally, visit the node.

We do this for every node in the tree.

Algorithm for Recursive Post Order Binary Tree Traversal

postOrder(root) {
    If root is NULL
        return
    postOrder(root->leftChild)
    postOrder(root->rightChild)
    print(root->value)
    return
}

The above algorithm is explain using the below example:


first-step-in-post-order-traversal

Here, starting at the root (8), you descend to the left child (3).

Visited Node:


second-step-in-post-order-traversal

At 3, you again descend to its left child (1).

Visited Node:


third-step-in-post-order-traversal

The node(1) does not have any children, so you immediately visit the node(1) and then go back to the node(3). After that, you descend to its right child (6).

Visited Node: 1


fourth-step-in-post-order-traversal

As with node(1), node(6) is also a leaf node with no children, so we visit the node (6) as well and go back to the node(3) again. As both left and right child of the node(3) are already visited, we visit the node(3) and go back to the node(8).

Visited Node: 1 6 3


fifth-step-in-post-order-traversal

At node(8), we visit its right child which is node(10).

Visited Node: 1 6 3


sixth-step-in-post-order-traversal

The node(10) does not have any left child, so we directly descent to the right child which is node(14). The node(14) does not have any children, so we visit the node(14) and go back to node(10).

Visited Node: 1 6 3 14


seventh-step-in-post-order-traversal

At node(10), both its children are either visited or not exists, so we visit the node (10) as well and go to the node (8) which also have both of its children visited. So, we visit this node as well.

Visited Node: 1 6 3 14 10 8

And just like that, we visited the whole binary tree.

Binary Tree Post-Order Traversal Path

From the above figures, we can deduce that if we add the edge to every NULL value and start walking in top to bottom and left to right path relative to the tree, then we are visiting each node at the third encounter. The below figure showns this,

ttbltr-walking-path-for-postorder-traversal

This information is useful when we want to find the postorder by looking at the tree structure. It also helps in finding the time complexity of the postorder operation logically.

C++ Program to Implement Postorder Traversal of the Binary Tree

C++
// C++ Program to illustrate how to implement the postorder
// traversal of a binary tree
#include <iostream>
using namespace std;

// node of the tree
struct TreeNode {
    int val;
    TreeNode *left, *right;
    TreeNode(int x)
    {
        this->val = x;
        this->left = NULL;
        this->right = NULL;
    }
};

// function for post order traversal of the given tree
void postOrderTraversal(TreeNode* node)
{
    // if the current node is null
    if (node == NULL)
        return;
    // Traverse the left first
    postOrderTraversal(node->left);
    // then traverse right
    postOrderTraversal(node->right);

    // finally visit the node
    cout << node->val << " ";
}

int main()
{
    // Creating the tree
    //          8
    //        /   \
    //       3     10
    //     /   \      \
    //    1     6      14
    TreeNode* root = new TreeNode(8);
    root->left = new TreeNode(3);
    root->right = new TreeNode(10);
    root->left->left = new TreeNode(1);
    root->left->right = new TreeNode(6);
    root->right->right = new TreeNode(14);

    // Perform post-order traversal
    cout << "Post-order traversal output: ";
    postOrderTraversal(root);
    cout << endl;

    return 0;
}

Output
Post-order traversal output: 1 6 3 14 10 8 

Complexity Analysis of Binary Tree Postorder Traversal

The complexity analysis of post order traversal is pretty simple.

Time Complexity of Recursive Post Order Tree Traversal

From the path diagram, we know that each node is encountered exactly three times. It means that N number of nodes are encountered 3N times. So,

Time complexity of the recursive post order binary tree traversal is: O(3N) = O(N)

where, N is the number of nodes in the tree.

For detailed mathematical analysis, refer to the article here.

Space Complexity of the Recursive Post Order Tree Traversal

According to algorithm, the program control will go first as deep as possible from the current node using recursion, and only after that it will visit the current node and return. As each recursive call creates a stack frame that lives in the memory till the function is executed completely so this will create as many stack frames as there are node in the path from current node to deepest node and only after visiting the deepmost node from there, the stack frame will start getting destroyed.

Now, the maximum amount of space needed at a time will be the number of node in the longest such path (which is apparently the height of the tree).

Due to this, space complexity of the recursive post order traversal will vary depending upon the structure of the tree.

tree-structure-types

For Degenerate Tree Structure,

Auxiliary Space Complexity is O(N), as N is the height of degenerate/skew tree.

For Balanced Tree Structrue,

Auxiliary Space Complexity is O(logN), as logN is the height for balanced binary tree.

where N is the number of nodes in the tree.

Iterative Post-Order Traversal of Binary Tree in C++

Due to the recursive nature of the problem, it is easy and efficient to implement the post order traversal using recursion. But we can also implement it using loops.

Algorithm for Iterative Post-Order Binary Tree Traversal in C++

The iterative approach uses a stack to simulate the recursive behavior.

  • Push the root node to the stack.
  • Initialize a temporary pointer to track the previously visited node.
  • Loop until the stack is empty:
    • Peek at the top node on the stack.
    • If the top node has no children or the previously visited node is its right child, visit the top node and pop it off the stack.
  • Otherwise:
    • If the top node has a right child and it hasn’t been visited yet, push the right child onto the stack.
    • If the top node has a left child and it hasn’t been visited yet, push the left child onto the stack.
    • After the loop completes, all nodes will have been visited in post-order.

C++ Program for Iterative Postorder Traversal of the Binary Tree

C++
// C++ Program to illustrate how to implement iterative post
// order traversal of binary tree
#include <iostream>
#include <stack>

using namespace std;

// tree node
struct TreeNode {
    int val;
    TreeNode *left, *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

// iterative post order traversal
void postOrderTraversal(TreeNode* root)
{
    // if the tree is empty
    if (root == NULL)
        return;

    // temporary stack to mimic the behaviour of the call
    // stack
    stack<TreeNode*> stack;

    // pointer to previously visited node
    TreeNode* prev = NULL;

    // starting by pushing root
    stack.push(root);

    while (!stack.empty()) {
        TreeNode* curr = stack.top();

        // If the current node has no children or its
        // children have been visited
        if (curr->left == NULL && curr->right == NULL
            || prev == curr->right
            || (prev == curr->left
                && curr->right == NULL)) {
            cout << curr->val << " ";
            stack.pop();
            prev = curr;
        }
        else {
            if (curr->right != NULL)
                stack.push(curr->right);
            if (curr->left != NULL)
                stack.push(curr->left);
        }
    }
}

int main()
{
    // Create nodes
    TreeNode* root = new TreeNode(8);
    root->left = new TreeNode(3);
    root->right = new TreeNode(10);
    root->left->left = new TreeNode(1);
    root->left->right = new TreeNode(6);
    root->right->right = new TreeNode(14);

    // Perform post-order traversal
    cout << "Post-order traversal output: ";
    postOrderTraversal(root);
    cout << endl;

    return 0;
}

Output
Post-order traversal output: 1 6 3 14 10 8 

Complexity Analysis of Iterative Post Order Traversal in C++

The time and space complexity of the post order traversal will be same as that of the recursive approach due to the necessary usage of the stack data structure.

Time Complexity: O(N)

Space Complexity: O(N) for degenerate or skewed, O(logN)

Related Articles:




Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads