题目:

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的更多相关文章

  1. 【Binary Tree Level Order Traversal】cpp

    题目: Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to ri ...

  2. 2016.6.24——vector<vector<int>>【Binary Tree Level Order Traversal】

    Binary Tree Level Order Traversal 本题收获: 1.vector<vector<int>>的用法 vector<vector<int ...

  3. 【遍历二叉树】04二叉树的层次遍历【Binary Tree Level Order Traversal】

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 给定一个二叉树,返回他的层次遍历的 ...

  4. 【Binary Tree Level Order Traversal II 】cpp

    题目: Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from ...

  5. 【遍历二叉树】05二叉树的层次遍历II【Binary Tree Level Order Traversal II】

    就把vector改成用栈类存放层次遍历的一层的序列 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ...

  6. 【Binary Tree Right Side View 】cpp

    题目: Given a binary tree, imagine yourself standing on the right side of it, return the values of the ...

  7. 【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 ...

  8. 【一天一道LeetCode】#107. Binary Tree Level Order Traversal II

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 来源: htt ...

  9. 【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 ...

随机推荐

  1. SQL Server存储过程(转载)

    Transact-SQL中的存储过程,非常类似于Java语言中的方法,它可以重复调用.当存储过程执行一次后,可以将语句缓存中,这样下次执行的时候直接使用缓存中的语句.这样就可以提高存储过程的性能. Ø ...

  2. js原型链接(二)和object类的create方法

    原型链的内部执行方式 <script> function Myclass(){ this.x=" x in Myclass"; } var obj=new Myclas ...

  3. php根据身份证号码计算年龄

    代码如下 复制代码 <?php function getAgeByID($id){         //过了这年的生日才算多了1周岁         if(empty($id)) return ...

  4. 自己一晚上总结的php基础知识!好累。好充实。

    为了巩固自己的基础提升自己的技术.花了一晚上的时间结合w3c上的非常基础的东西,和自己的部分见解,写了不少,望大神们指正,指导.. <?php /* 这段话必须要写在开篇啊!死老猫,你又刺激我! ...

  5. 设计师眼中功能强大的Xcode

    作为设计师,不仅要能创造出移动为先的新产品,更要了解能创造出优秀移动作品的工具.这个实现过程可以让我们的设计更加优秀. 过去两个月,我每天在 Xcode 上花费的时间大约有 10 个小时,我学到了很多 ...

  6. [.ashx檔?泛型处理程序?]基础入门#5....ADO.NET 与 将DB里面的二进制图片还原 (范例下载 & 大型控件的ImageField)

    [.ashx檔?泛型处理程序?]基础入门#5....ADO.NET 与 将DB里面的二进制图片还原 (范例下载 & 大型控件的ImageField) http://www.dotblogs.c ...

  7. ASP.NET Core文章汇总

    现有Asp.Net Core 文章资料,2016 3-20月汇总如下 ASP.NET Core 1.0 与 .NET Core 1.0 基础概述 http://www.cnblogs.com/Irvi ...

  8. [terry笔记]RMAN综合学习之配置

    [terry笔记]RMAN综合学习之备份http://www.cnblogs.com/kkterry/p/3308405.html [terry笔记]RMAN综合学习之恢复 http://www.cn ...

  9. 【J2EE】Hibernate

    Hibernate是面向Java环境的对象/关系数据库映射工具,管理Java应用和数据库之间的映射关系,提供数据查询和获取数据的方法,可以大幅减少使用JDBC处理数据持久化的时间. 使用Eclipse ...

  10. 向plsql中导入数据

    1.TOOLS-->ODBC IMPORTER 2.TOOLS-->TEXT IMPORTER3.sqlldr userid=zj/zj@orcl control=D:\test.ctl ...