(LeetCode)145. 二叉树的后序遍历(非递归)

算法思路:因为在后序遍历的时候只有当前节点的左子树和右子树均访问完后,才能访问当前节点。

所以这里就涉及到入栈出栈的问题了。

之前写中序的时候,只要指针非空就可以入栈,然后更新为左孩子,指针变空就访问栈顶元素,然后更新为右孩子并出栈

但是现在指针非空入栈,指针变空的时候不能直接访问栈顶元素了,因为栈顶元素的右子树(或者右孩子)还没访问呢

我的想法是每次节点指针出栈入栈的时候把相应的一个bool变量也在另一个bool栈中进行相同的出栈入栈操作

这些bool变量标识的是相应节点能否被访问,起始情况下均为false

然后第一次遇到之后把相应的bool值改为true,这样下一次就可以访问节点

也就是这部分代码

temp = nodeStack.top();
nodeStack.pop();
if(flagStack.top() == false){//第一次出现在栈顶
    flagStack.pop();
    flagStack.push(true);
    nodeStack.push(temp);
    curr = temp->right;
}

二叉树后序遍历非递归正确代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> array;
        if(!root)   return array;
        TreeNode* curr = root;
        TreeNode* temp = NULL;
        stack<TreeNode*> nodeStack;
        stack<bool> flagStack; //辅助说明当前栈顶可以访问还是继续等待右子树的后序遍历
        while(curr != NULL || !nodeStack.empty()){
            while(curr){//当前节点不为空
                nodeStack.push(curr);
                flagStack.push(false);
                curr = curr->left;
            }
            if(!nodeStack.empty()){
                temp = nodeStack.top();
                nodeStack.pop();
                
                if(flagStack.top() == false){//第一次出现在栈顶
                    flagStack.pop();
                    flagStack.push(true);
                    nodeStack.push(temp);
                    curr = temp->right;
                }
                else{
                    array.push_back(temp->val);
                    flagStack.pop();
                    curr = NULL;
                }
            }
        }
        return array;
    }
};

之前写中序非递归遍历的时候比较简单,请看代码:

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> returnArray;
        stack<struct TreeNode*> nodeStack;//栈的元素是指针,而不是相应结构体
        struct TreeNode* p = root;
        while(p != NULL || !nodeStack.empty()){
            if(p){
                nodeStack.push(p);
                p = p->left;
            }
            else if(!nodeStack.empty()){
                //此时nodeStack.top()就是一个没有左子节点的节点,所以直接入数组,遍历顺序是:左中右
                returnArray.push_back(nodeStack.top()->val);
                p = nodeStack.top()->right;
                nodeStack.pop();
            }
            
        }
        return returnArray;
    }
};

第一次的错误代码(超时)

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> array;
        if(!root)   return array;
        TreeNode* p = root;
        stack<TreeNode*> nodeStack;
        stack<bool> flagStack; //辅助说明当前栈顶可以访问还是继续等待右子树的后序遍历
        while(p != NULL || !nodeStack.empty()){
            if(p){//当前节点不为空
                nodeStack.push(p);
                flagStack.push(false);
                p = p->left;
            }
            else if(!nodeStack.empty()){
                //当前节点为叶子节点
                if(flagStack.top()){
                    array.push_back(nodeStack.top()->val);
                    flagStack.pop();
                    nodeStack.pop();
                    p = nodeStack.top();
                }
                else{
                    p = nodeStack.top()->right;
                    flagStack.pop();
                    flagStack.push(true);   
                }
            }
        }
        return array;
    }
};

第二次错误代码(解答错误 )

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> array;
        if(!root)   return array;
        TreeNode* curr = root;
        TreeNode* temp = NULL;
        stack<TreeNode*> nodeStack;
        stack<bool> flagStack; //辅助说明当前栈顶可以访问还是继续等待右子树的后序遍历
        while(curr != NULL || !nodeStack.empty()){
            while(curr){//当前节点不为空
                nodeStack.push(curr);
                flagStack.push(false);
                curr = curr->left;
            }
            if(!nodeStack.empty()){
                //先开始执行的时候是因为curr为NULL才会进到这个while循环中
                // array.push_back(nodeStack.top()->val);
                // curr = nodeStack.top()->right;
                temp = nodeStack.top();
                nodeStack.pop();
                if(flagStack.top() == false){//第一次出现在栈顶
                    flagStack.pop();
                    flagStack.push(true);
                    nodeStack.push(temp);
                    curr = temp->right;
                }
                else{
                    array.push_back(temp->val);
                    curr = NULL;
                }
            }
        }
        return array;
    }
};

参考blog:https://www.cnblogs.com/SHERO-Vae/p/5800363.html

猜你喜欢

转载自blog.csdn.net/liuxiang15/article/details/82348813