【Binary Tree Post order Traversal】cpp
题目:
Given a binary tree, return the postorder traversal of its nodes' values.
For example:
Given binary tree {1,#,2,3},
1
\
2
/
3
return [3,2,1].
Note: Recursive solution is trivial, could you do it iteratively?
代码:
stack 1:
/**
* 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> ret;
if (!root) return ret;
stack<TreeNode *> sta;
sta.push(root);
while ( !sta.empty() ){
TreeNode *tmp = sta.top();
sta.pop();
if ( tmp->left || tmp->right ){
TreeNode *l = tmp->left, *r = tmp->right;
tmp->left = tmp->right = NULL;
sta.push(tmp);
if (r) sta.push(r);
if (l) sta.push(l);
}
else{
ret.push_back(tmp->val);
}
}
return ret;
}
};
stack 2:
/**
* 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> ret;
stack<TreeNode *> sta;
TreeNode *curr = root;
while ( !sta.empty() || curr )
{
if (curr)
{
sta.push(curr);
curr = curr->left;
}
else
{
curr = sta.top();
if ( !curr->right )
{
ret.push_back(curr->val);
sta.pop();
curr = NULL;
}
else
{
curr = curr->right;
sta.top()->right = NULL;
}
}
}
return ret;
}
};
tips:
上述两个代码都是基于stack的操作完成的后序遍历二叉树。
个人更喜欢stack 1的风格,思路如下:
0. 先压root入栈
1. 栈顶元素出栈
2. 如果其左右都为空:则可以直接推入ret中
否则:先将这个节点的left和right保存下来;再将这个节点与其子分支剪断(right left都置为NULL);再按照tmp, right, left的顺序入栈。
循环1~2,直到栈空,则后序遍历完成
网上一些答案很多都是基于stack 2这种方法,维护一个当前指针curr。
这个思路就是一条道走到黑的思路(DFS深搜)
1. curr不为NULL,则一直沿着left的方向走,直到走到NULL
2. 只要curr为NULL,则一定是栈顶元素的left已经没有了(走到头了),则需要判断栈顶元素的right是否为NULL;
如果为NULL,则证明栈顶元素的left和right都访问过了,栈顶元素的val可以推入ret;
如果不为NULL,则证明其right还得遍历。这个时候,需要完成两件事情:
a. curr向right走
b. 栈顶元素的right置为空(标记再次访问栈顶元素,其right已经再curr= curr->right的带领下处理过了)
其实stack 2的思路跟stack 1类似,都是需要判断栈顶元素的left和right是否都NULL,再决定栈顶元素的val是否推入ret。
==========================================
stack1和2的方法都在遍历之后对原有的数据结构损坏了(这显然是不合理的),因此改写了如下的代码,不递归不损坏原有数据结构
/**
* 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> ret;
stack<TreeNode *> sta;
TreeNode *curr = root;
std::map<TreeNode *, bool> r_visited;
while ( !sta.empty() || curr )
{
if (curr)
{
sta.push(curr);
curr = curr->left;
}
else
{
curr = sta.top();
if ( !curr->right || r_visited.find(curr)!=r_visited.end()?r_visited[curr]:false )
{
ret.push_back(curr->val);
sta.pop();
curr = NULL;
}
else
{
curr = curr->right;
r_visited[sta.top()] = true;
}
}
}
return ret;
}
};
tips:
之前如果curr->right访问过了,就直接sta.top()->right=NULL了,显然破坏了原有的数据结构。
这里用一个hashmap来保存访问过TreeNode的right是否被访问了。多了一个hashmap,但保住了原有数据结构。
=======================================================
第二次过这道题,就看看非递归的写法。找到了下面的一个blog:http://noalgo.info/832.html
用类似先序遍历的代码,再做一次翻转,就得到了后续遍历的结果。
/**
* 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> ret;
stack<TreeNode*> sta;
if ( root ) sta.push(root);
while ( !sta.empty() )
{
TreeNode* tmp = sta.top();
sta.pop();
ret.push_back(tmp->val);
if ( tmp->left ) sta.push(tmp->left);
if ( tmp->right ) sta.push(tmp->right);
}
std::reverse(ret.begin(), ret.end());
return ret;
}
};
后续遍历的顺序是:left right mid
因此,只要按照 mid right left的顺序遍历一次 再做reverse就可以了。
这个思路很巧妙。
========================================
做了这道题 突然想到了二叉树最小公共祖先,搜了一下http://blog.csdn.net/luckyxiaoqiang/article/details/7518888
先大概过一遍,心里有数。
【Binary Tree Post order Traversal】cpp的更多相关文章
- 【Binary Tree Level Order Traversal】cpp
题目: Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to ri ...
- 2016.6.24——vector<vector<int>>【Binary Tree Level Order Traversal】
Binary Tree Level Order Traversal 本题收获: 1.vector<vector<int>>的用法 vector<vector<int ...
- 【遍历二叉树】04二叉树的层次遍历【Binary Tree Level Order Traversal】
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 给定一个二叉树,返回他的层次遍历的 ...
- 【Binary Tree Level Order Traversal II 】cpp
题目: Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from ...
- 【遍历二叉树】05二叉树的层次遍历II【Binary Tree Level Order Traversal II】
就把vector改成用栈类存放层次遍历的一层的序列 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ...
- 【Binary Tree Right Side View 】cpp
题目: Given a binary tree, imagine yourself standing on the right side of it, return the values of the ...
- 【Binary Tree Maximum Path Sum】cpp
题目: Given a binary tree, find the maximum path sum. The path may start and end at any node in the tr ...
- 【一天一道LeetCode】#107. Binary Tree Level Order Traversal II
一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 来源: htt ...
- 【Leetcode】【Easy】Binary Tree Level Order Traversal II
Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left ...
随机推荐
- 数据库mysql的基本命令
问题分析 当数据量很大的时候,所有数据都集中在一个文本文件中的话,读写会很困难,内存消耗大,速度很慢 操作很麻烦,因为读写都要根据指定的格式尽心解析,不通用 每次获取数据都要全部数据重新读写,不能通过 ...
- vim 文字插入
我们知道VIM中,普通的复制和粘贴都是YY和PP.那么怎么将vim以外的文件插入到vim编辑器中呢!这是个问题: 首先我们要选中想要插入的文字,如: 然后进入vim插入模式:SHIFT + Inser ...
- SQL Server存储过程(转载)
Transact-SQL中的存储过程,非常类似于Java语言中的方法,它可以重复调用.当存储过程执行一次后,可以将语句缓存中,这样下次执行的时候直接使用缓存中的语句.这样就可以提高存储过程的性能. Ø ...
- Web serviser请求通道在等待 00:00:59.6479648 以后答复时超时。增加传递给请求调用的超时值,或者增加绑定上的 SendTimeout 值。分配给此操作的时间可能是更长超时的一部分。
可以把sendTimeout调长一点试试 .net webService 中: 设置这些参数,延长连接时间, closeTimeout="00:10:00" openTimeout ...
- SublimeText快捷键大全(附GIF演示图)
Sublime Text是码农必备之神器,有助于码农快速开垦,如果掌握了Sublime强大的快捷键就可以飞起来了.下面下载吧小编汇总了SublimeText支持的全部快捷键(适用SublimeText ...
- Nginx+Tomcat+Memcached集群
Tomcat集群session同步方案有以下几种方式: 使用tomcat自带的cluster方式,多个tomcat间自动实时复制session信息,配置起来很简单.但这个方案的效率比较低,在大并发下表 ...
- C++判断对称三位数素数
题目内容:判断一个数是否为对称三位数素数.所谓“对称”是指一个数,倒过来还是该数.例如,375不是对称数,因为倒过来变成了573. 输入描述:输入数据含有不多于50个的正整数(0<n<23 ...
- VPS centos 6 安装图形界面
在某种场合之下,我们使用的Linux还是要选择安装桌面环境的,所以在这里介绍一下如何给没有安装桌面环境的系统安装桌面环境.以Centos 6.5 为例演示一下如何安装桌面环境. 工具/原料 Linux ...
- C语言-L Buffer is too small && 0 解决方法
问题如下: 问题出在程序语句(见下): 其中,字符串p1和p2分别指向某个字符串,p是定义的一个字符数组.问题出现在对strlen()的使用,这个函数计算的字符串长度是不包括'\0'的,所以在设置第二 ...
- LayoutInflater中四种类型inflate方法的介绍
转自:http://blog.csdn.net/aa4790139/archive/2011/05/07/6401556.aspx 第一种: public View inflate (int reso ...