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?

后序遍历:左孩子->右孩子->根节点

后序遍历最关键的是利用一个指针保存前一个访问过的信息,避免重复访问。

思路一:

左、右孩子是交叉入栈的,当出栈时,就存在如何从左孩子转向右孩子同时避免重复访问的问题。一个节点值被取出来时,它的左右子节点要么不存在,要么已经被访问过。所以,用head来保存上一个已访问元素的信息,然后判断是否为栈顶元素的左右孩子来实现避免重复访问,至于从左转向右,入栈的顺序已经解决这个问题。原代码

/**
* Definition for binary tree
* 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> res;
stack<TreeNode *>stk;
if(root) stk.push(root);
TreeNode *head=root;
while( !stk.empty())
{
TreeNode *top=stk.top();
if(( !top->left&& !top->right)||top->left==head||top->right==head)
{ //两种情况:一、到达叶节点;二、前一元素是栈顶的左、右孩子即被访问过
res.push_back(top->val);
stk.pop();
head=top;
}
else //结合栈的特点和后边遍历的顺序,右先进
{
if(top->right)
stk.push(top->right);
if(top->left)
stk.push(top->left);
}
}
return res;
}
};

思路二:

【后序遍历二叉树的步骤:先遍历二叉树的左子树,再遍历二叉树的右子树,最后访问根结点。非递归实现时,用一个栈模拟遍历过程。由于访问完左子树后访问右子树,栈中元素要起到转向访问其右子树的作用,但是不能像先序和中序遍历那样出栈即可,因为根结点时最后访问的。那么什么时候出栈呢?我们需要一个指针pre来记录前一次访问的结点。如果pre是根结点的右子树,则说明根结点的右子树访问完了,此时根结点就可以出栈了(源代码)】。过程:将左孩子不停的压入栈中,直到由root=root->left得到root为空,然后将栈顶元素的值存入res,用pre记录栈顶元素(在后来可以避免重复访问)。在下次循环中,因,root为空,所以跳过if进入判断else if实现左孩子向右孩子的转变。整体上,左孩子出栈以后,右孩子入栈,用pre记录右孩子,右孩子出栈,利用stk.top()->right !=pre来避免重复访问。

/**
* Definition for binary tree
* 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> res;
stack<TreeNode *> stk; TreeNode *pre=NULL;
while(root|| !stk.empty())
{
if(root)
{
stk.push(root);
root=root->left;
}
else if(stk.top()->right !=pre) //判断stk.top()->right是否被访问过
{
root=stk.top()->right;
pre=NULL;
}
else
{
res.push_back(stk.top()->val);
pre=stk.top();
stk.pop();
}
}
return res; }
};

思路三:递归版

class Solution {
public:
vector<int> postorderTraversal(TreeNode *root)
{
vector<int> res;
postOrderTrav(root,res);
return res;
}
void postOrderTrav(TreeNode *root,vector<int> &res)
{
if(root==NULL) return;
postOrderTrav(root->left,res);
postOrderTrav(root->right,res);
res.push_back(root->val);
}
};

最新文章

  1. std::bind(二)
  2. 我写了一个java实体类,implements了Serializable接口,然后我如何让serialversionUID自动生成
  3. oracle查看表占磁盘大小
  4. EXTJS 4.2 资料 控件之Window窗体添加html
  5. css background-position:x% y%
  6. 写自己的第二级处理器(3)——Verilog HDL行为语句
  7. java类到底是如何加载并初始化的?
  8. Android简易实战教程--第二话《两种进度条》
  9. IPD体系向敏捷开发模式转型实施成功的四个关键因素
  10. TCP/IP学习20180710-数据链路层-ICMP协议
  11. Scrapy基础(三) ------xpath基础
  12. js计算本地时间
  13. java method.isBridge
  14. July_One_Week—linked list
  15. HashMap几个需要注意的知识点
  16. 404 Note Found 队-Alpha4
  17. STM32F10X FLASH and SRAM size
  18. Python ---- super()使用
  19. vmware vSphere克隆与快照技术
  20. The Dangers of the Large Object Heap(转载,LOH内存碎片情景重现)

热门文章

  1. 关于 Windows 10 字体安装目录的问题
  2. 180713-Spring之借助Redis设计访问计数器之扩展篇
  3. 8月leetcode刷题总结
  4. 凸包算法(Graham扫描法)详解
  5. 有个AI陪你一起写代码,是种怎样的体验?| 附ICLR论文
  6. LeetCode 240——搜索二维矩阵 II
  7. 今日头条 2018 AI Camp 6 月 2 日在线笔试编程题第一道——最大连续区间和扩展
  8. Juice账号
  9. 将footer固定在页面最下方
  10. mysql 相同表结构拷贝数据