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);
}
};

[Leetcode] Binary tree postorder traversal二叉树后序遍历的更多相关文章

  1. LeetCode:145_Binary Tree Postorder Traversal | 二叉树后序遍历 | Hard

    题目:Binary Tree Postorder Traversal 二叉树的后序遍历,题目要求是采用非递归的方式,这个在上数据结构的课时已经很清楚了,二叉树的非递归遍历不管采用何种方式,都需要用到栈 ...

  2. LeetCode OJ:Binary Tree Postorder Traversal(后序遍历二叉树)

    Given a binary tree, return the postorder traversal of its nodes' values. For example:Given binary t ...

  3. [Leetcode] Binary tree inorder traversal二叉树中序遍历

    Given a binary tree, return the inorder traversal of its nodes' values. For example:Given binary tre ...

  4. [LeetCode] Binary Tree Postorder Traversal 二叉树的后序遍历

    Given a binary tree, return the postorder traversal of its nodes' values. For example: Given binary ...

  5. [leetcode]94. Binary Tree Inorder Traversal二叉树中序遍历

    Given a binary tree, return the inorder traversal of its nodes' values. Example: Input: [1,null,2,3] ...

  6. 94 Binary Tree Inorder Traversal(二叉树中序遍历Medium)

    题目意思:二叉树中序遍历,结果存在vector<int>中 解题思路:迭代 迭代实现: /** * Definition for a binary tree node. * struct ...

  7. 144 Binary Tree Preorder Traversal(二叉树先序遍历Medium)

    题目意思:二叉树先序遍历,结果存在vector<int>中 解题思路:1.递归(题目中说用递归做没什么意义,我也就贴贴代码吧) 2.迭代 迭代实现: class Solution { pu ...

  8. leetcode Binary Tree Postorder Traversal 二叉树后续遍历

    先给出递归版本的实现方法,有时间再弄个循环版的.代码如下: /** * Definition for binary tree * struct TreeNode { * int val; * Tree ...

  9. C++版 - LeetCode 145: Binary Tree Postorder Traversal(二叉树的后序遍历,迭代法)

    145. Binary Tree Postorder Traversal Total Submissions: 271797 Difficulty: Hard 提交网址: https://leetco ...

随机推荐

  1. OSG-交互

    本文转至http://www.cnblogs.com/shapherd/archive/2010/08/10/osg.html 作者写的比较好,再次收藏,希望更多的人可以看到这个文章 互联网是是一个相 ...

  2. 微信小程序如何性能测试?

    背景: 微信小程序作为手机页面的一种,相比传统的网站和应用来说存在比较特殊的地方: 1.  开发者往往对程序做了限制,只能通过微信客户端访问 2.  通过微信的Oauth进行认证 这样往往会导致我们的 ...

  3. ReadyAPI 教程和示例(二)

    声明:如果你想转载,请标明本篇博客的链接,请多多尊重原创,谢谢! 本篇使用的 ReadyAPI版本是2.5.0 接上一篇: 4.修改SoapUI测试 本节将演示如何为测试用例添加测试步骤以及更改请求参 ...

  4. 教你一招,提升你Python代码的可读性,小技巧

    Python的初学者,开发者都应该知道的代码可读性提高技巧,本篇主要介绍了如下内容: PEP 8是什么以及它存在的原因 为什么你应该编写符合PEP 8标准的代码 如何编写符合PEP 8的代码 为什么我 ...

  5. CodeForces - 913C(二进制)

    链接:CodeForces - 913C 题意:给出 n 瓶饮料的花费 C 数组,每瓶的体积是 2^(i-1) 升,求至少买 L 升的最少花费. 题解:二进制数的组合可以表示任何一个数.第 i 的饮料 ...

  6. 78[LeetCode] Subsets

    Given a set of distinct integers, nums, return all possible subsets (the power set). Note: The solut ...

  7. [leetcode-784-Letter Case Permutation]

    Given a string S, we can transform every letter individually to be lowercase or uppercase to create ...

  8. nodejs在linux环境下安装更新方式

    #检查是否已经安装 rpm -qa | grep python #查版本 python #最好是重新安装 Python推荐版本( >= v2.5.0 & < 3.0.0 ),否则影 ...

  9. RXSwift --UITableView之初探

    对于RXSwift中的一些基本概念和说明请参看其他文章,接下来我们使用RXSwift一步一步去构建TableView,从简单到复杂.iOS开发过程中tableView的使用率是最高的,他的一些代理方法 ...

  10. TCP系列28—窗口管理&流控—2、延迟ACK(Delayed Acknowledgments)

    一.简介 之前的内容中我们多次提到延迟ACK(Delayed Ack),延迟ACK是在RFC1122协议中定义的,协议指出,一个TCP实现应该实现延迟ACK,但是ACK不能被过度延迟,协议给出延迟AC ...