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为什么没有迭代器

 

posted @ 2019-02-22 01:16  lightmare  阅读(90)  评论(0编辑  收藏  举报