145. 二叉树的后序遍历【力扣】

题意理解

如题

问题分析

递归解法

非递归解法

用栈,再用一个指示上一个访问节点,用于根节点判断是否已经回退还是访问右子树。

大思路是,向左走到底 -- 如果右子树存在,向右一步走 -- 先左走到底。

其中,如果右子树不存在,或者右子树存在但是被访问过了,访问当前节点,再回退上一个结点(弹栈即可)。

为了标记右子树是否被访问,可以看上一次访问的是否是自己的右孩子,如果是右孩子,表明访问过了,如果不是右孩子,表明没有被访问过。

其他

链接

    vector postorderTraversal(TreeNode* root) {
        vector res;       
        stack st;
        if (root == nullptr) {    //空树
            return res;    //直接返回空序列
        }
        TreeNode* p = root;
        while (p) {    //初始化,向左走到最左节点
            st.push(p);
            p = p -> left;
        }
        TreeNode* last_visited;    //记录上一个别访问节点
        while (!st.empty()) {    //栈不空
            p = st.top();    //弹出最左节点
            st.pop();    
            if (p -> right == nullptr || last_visited == p -> right) {    //左子树必为空,当右子树为空,或者右节点是上一个被访问节点(右子树访问完)
                res.push_back(p -> val);            //输出当前节点        
                last_visited = p;    //重置上一次访问节点
            }
            else {    //右子树存在
                st.push(p);    //再把当前节点入栈
                p = p -> right;    //向右一步
                while (p) {    //向左走到底(为下一循环做准备)
                    st.push(p);
                    p = p -> left;
                }              
            }
        }
        return res;
    }
    vector postorderTraversal(TreeNode* root) {
        if (!root) {
            return vector{};                                                                 
        }
        vector res{};
        vector l_vector = postorderTraversal (root -> left);    //左子树的后序遍历
        vector r_vector = postorderTraversal (root -> right);    //右子树的后序遍历
        res.insert (res.end(), l_vector.begin(), l_vector.end());    //插入左子树遍历结果
        res.insert (res.end(), r_vector.begin(), r_vector.end());    //插入右子树遍历结果
        res.push_back (root -> val);    //插入根
        return res;
    }

 

    vector postorderTraversal(TreeNode* root) {        
        vector res;
        if (root == nullptr) {
            return res;
        }
        stack st1;    //存节点
        stack st2;    //存倒过来的后序序列
        
        st1.push(root);    //入根节点
        while (!st1.empty()) {    //栈不空
            TreeNode* p = st1.top();    //出栈,
            st2.push(p -> val);    //拨开节点内的值
            st1.pop();    //入后序序列栈
            if (p -> left) st1.push(p -> left);    //根处理完了,先入栈左节点
            if (p -> right) st1.push(p -> right);    //再入栈右节点,因为后序是先左后右再根,入第一个栈是先左后右,入第二个栈变成了先右后左,最后输出的时候就又变回先左后右了

        }
        while (!st2.empty()) {
            res.push_back(st2.top());
            st2.pop();
        }
        return res;
    }

 

你可能感兴趣的:(算法,STL,工作刷题)