zoukankan      html  css  js  c++  java
  • LeetCode145. Binary Tree Postorder Traversal

    题目 

    给定一个二叉树,返回它的 后序 遍历。

    示例:

    输入: [1,null,2,3]  
       1
        
         2
        /
       3 
    
    输出: [3,2,1]

    进阶: 递归算法很简单,你可以通过迭代算法完成吗?


    考点


    思路


    代码

    1.递归

    
    //递归:左-右-根
    class Solution {
    public:
        vector<int> postorderTraversal(TreeNode* root) {
            vector<int> ret;
            postOrder(root,ret);
            return ret;
        }
    
        void postOrder(TreeNode* root, vector<int> &ret)
        {
            if(!root) return ;
            postOrder(root->left,ret);
            postOrder(root->right,ret);
            ret.push_back(root->val); 
        }
    };
    

    2.迭代+2个辅助栈

    注意先root入栈。while只做栈空判断。和preorder,inorder不一样,否则会内存泄漏。curNode写在循环体里面,pop完再写curNode=s1.top(); 是错的。调用空stack的top()是未定义行为。所以要一开始写curNode。

    //迭代+2个栈
    class Solution {
    public:
        vector<int> postorderTraversal(TreeNode* root) {
            vector<int> ret;
            stack<TreeNode*> s1;//缓存栈
            stack<TreeNode*> s2;//弹出栈
            if (!root) {
                return ret;
            }
             
            s1.push(root);
            while(!s1.empty())
            {
                TreeNode* curNode=s1.top();//curNode写在里面,while只做栈空判断。和preorder,inorder不一样,否则会内存泄漏
                //s1.top->s2
                s2.push(s1.top());
                s1.pop(); 
                if(curNode->left)
                    s1.push(curNode->left);
                if(curNode->right)
                    s1.push(curNode->right);             
                //curNode=s1.top();     // 调用空stack的top()是未定义行为。
                                            
            }
    
            while(!s2.empty())//stack没有迭代器,不能使用c++11的range loop语法,所以用while遍历。
            {
                ret.push_back(s2.top()->val);
                s2.pop();
            }
            return ret;
    
        }
    };
    

    3.非递归+一个栈

    两个指针。c:当前节点,stack.top().h:上一层打印的节点

    1.将root入栈。h=root,c=nullptr

    2.c的三种情况

    c=stack.top()

    2.1 c->left 不为空 且 h不等于c->left 且 h不等于 c->right 。没有访问过c->left,c->left入栈 

    2.2 c->right 不为空 且 h不等于c->right  。没有访问过c->right,c->right入栈

    2.3 不属于上面两种情况。h = stack. top() ; stack.pop() 。 打印h

    3.重复2 .直到stack空

    //迭代+1个栈
    class Solution {
    public:
        vector<int> postorderTraversal(TreeNode* root) {
            vector<int> ret;
            stack<TreeNode*> stack;
            stack.push(root); 
            TreeNode* curNode=nullptr;
            TreeNode* lastNode=root;
            if(!root)//注意入口判断!!
            return ret;
    
            
            while(!stack.empty())
            {
                curNode=stack.top();
                //left未处理:如果h==c->left,说明刚处理完left。如果h==c->right,说明刚处理完right,由于是后序,那说明left已经处理完了。
                if(curNode->left&&lastNode!=curNode->left&&lastNode!=curNode->right)
                {
                    stack.push(curNode->left);
                }
                //left处理完,right未处理
                else if(curNode->right&&lastNode !=curNode->right)
                {
                    stack.push(curNode->right);
                }
                //left,right都处理完,处理root
                else 
                {
                    lastNode=stack.top();
                    stack.pop();
                    ret.push_back(lastNode->val);
                } 
            } 
            return ret; 
        }
    };

    问题

    -----------------------bug:调用空stack的top()是未定义行为。------------- --- -------------------

    stack<int>的内部容器是deque<int>,对stack调用top()相当于调用内部deque容器的back()。

    C++标准(§ 23.2.3, Table 100)规定,对于顺序容器a,函数a.back()的实现如下:

    {

    auto tmp = a.end();

    --tmp;

    return *tmp;

    }

    在一个空的stack中,内部deque的begin() == end()。

    而且标准§ 24.2.6又规定,对一个双向/随机访问迭代器 r 执行前置operator--操作的前提条件是存在另一个迭代器 s 可以满足r == ++s。

    由于空stack的top()对内部deque容器的begin()执行了--操作,所以在没有任何优化的情况下,调用top()会导致编译无法通过。

    ref:【图解数据结构】 二叉树遍历

    C++ queue为什么没有迭代器

  • 相关阅读:
    flask+Gunicorn+nginx部署
    配置Django实现数据库读写分离
    mysql分库分表
    python的反射
    flask-restful的使用
    spring源码(4)
    spring源码(3)
    spring源码(2)
    spring源码(1)
    tomcat8.5 配置数据源
  • 原文地址:https://www.cnblogs.com/lightmare/p/10425080.html
Copyright © 2011-2022 走看看