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