Postorder traversal of binary tree (recursive method and iterative method (non recursive method)) - C++

  Statement: the original title of this article mainly comes from Force buckle ***

The traversal of binary tree includes pre order traversal, middle order traversal, post order traversal and hierarchical traversal. The basic knowledge points of binary tree can refer to the previous blog of blogger( Introduction to basic knowledge points of binary tree (the most concise in the whole network) ), the preorder traversal of binary tree can refer to the blogger's blog( Preorder traversal of binary tree (recursive method and iterative method (i.e. non recursive method)) - C++ ), the middle order traversal can refer to the blogger's blog( Order traversal in binary tree (recursive method and iterative method (non recursive method)) - C++ ), this paper mainly summarizes the subsequent traversal of binary tree.

1, Postorder traversal of binary tree

Backward traversal is to traverse the left child node first, then the right child node, and finally the parent node, that is, the traversal order:

left -> right -> parent

The following is the original question of force deduction. Write a post order traversal program.

Given the root node of a binary tree   root  , Returns its postorder traversal.

Example 1:

Input: root = [1,null,2,3]
Output: [1,3,2]

1.1 recursive method

The recursive method mainly uses the compiler stack to automatically press the recursive function parameters and local variables, and traverses the binary tree in the order of post order, with only one access to the binary tree. The following is a specific example code:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        if(root == nullptr)
            return datas;
        if(root->left != nullptr)
            postorderTraversal(root->left);
        if(root->right != nullptr)
            postorderTraversal(root->right);
        datas.push_back(root->val);
        return datas;
    }
private:
    vector<int> datas;
};

result:

   1.2 iterative method

Since it is difficult to understand and implement the subsequent traversal if it is implemented according to the normal iterative idea, a rule can be found by carefully observing the following preamble and subsequent traversal sequence:

  1. Preorder traversal:   parent ——> left ——> right
  2. Preorder traversal:   left ——> right ——>   parent,
  3. Traverse the subsequent traversals in reverse order, then: parent -- > right -- >   left

By observing 1 and 3, we can find that both of them traverse the parent node first, and then the left and right child nodes. This traversal method is easy to be implemented in code in the iterative method, so we can traverse the binary tree nodes in the opposite order of subsequent traversal, and finally reverse the traversal result array.

1.2.1 specific implementation steps

a1 push the parent node onto the stack

if (root == nullptr)
return datas;
TreeNode* cur = root;
std::stack<TreeNode*> nodeStack;
nodeStack.push(cur);

a2 access the parent node, then stack the left child node, and finally stack the right child node

The purpose of this is to traverse the parent node, then the right child node, and finally the left child node when popping the stack.

cur = nodeStack.top();
nodeStack.pop();
datas.push_back(cur->val);
if (cur->left != nullptr)
nodeStack.push(cur->left);
if (cur->right != nullptr)
nodeStack.push(cur->right);

a3 cycles steps a1 and a2 until the entire stack is empty

while (!nodeStack.empty())
{
    cur = nodeStack.top();
    nodeStack.pop();
    datas.push_back(cur->val);
    if (cur->left != nullptr)
        nodeStack.push(cur->left);
    if (cur->right != nullptr)
        nodeStack.push(cur->right);
}

a4 reverse the traversal result array

std::reverse(datas.begin(), datas.end());

1.2.2 complete code implementation

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        if(root == nullptr)
            return datas;
        TreeNode* cur = root;
        std::stack<TreeNode *> nodeStack;
        nodeStack.push(cur);
        while(!nodeStack.empty())
        {
            cur = nodeStack.top();
            nodeStack.pop();
            datas.push_back(cur->val);
            if(cur->left != nullptr)
                nodeStack.push(cur->left);
            if(cur->right != nullptr)
                nodeStack.push(cur->right);
        }
        std::reverse(datas.begin(), datas.end());        
        return datas;
    }
private:
    vector<int> datas;
};

result:

1.3 summary

Through the ingenious use of post order traversal, we can think about whether we can solve the problem by changing the problem from one angle, such as reversal and rotation, compared with the existing easy to implement methods, which can greatly improve the efficiency and solve the problem.

Tags: Algorithm data structure

Posted on Sat, 04 Dec 2021 15:40:14 -0500 by LuiePL