二叉树的后序遍历
2016-04-15 12:49
190 查看
这是二叉树的三种主要遍历方式的最后一种了,前面两种我们已经讨论过,后序遍历其实就是将策略转换成了"左-右-根",其他方面跟前两种一样,都是深搜的逻辑。前两种详见以下链接:
前序遍历:点击打开链接
中序遍历:点击打开链接
好,回到已经用了三次的那张老图:
后序遍历的结果应该是:DEBFGCA
这也是三种遍历模型中最难的一个。因为要先访问左右两个孩子,再访问其父节点。如果按照以前的方法,类似地设计栈对数据流的巧妙控制,虽然最终也能做出来,但确实比较难。好在我查到一个博主的文章,他给出了一个更简单的方法。详见:点击打开链接
在此,我把这种方法再按我自己的理解,更简单地复述一遍:
我们在处理这棵树的时候,还是可以先建立一个栈,按照“根-右-左”的顺序依次将节点添加到栈,但是根据后序遍历的规则,我们现在并不能访问这些节点,什么时候可以了呢?当现在访问到的节点是叶子节点或者是回溯时到达的节点(例如,访问完D之后,访问E,之后回溯到B,那么B就是回溯时到达的节点,此时是应该被访输出的)
好了,再理一下思路,按照“根-右-左”的顺序添加节点到栈中(因为栈是先进后出,所以输出时,正好和后序遍历的策略是一致的),但是每次在添加节点之前都必须先检查这个节点(是不是叶子?是不是回溯的?)如果是,则访问该节点,输出值。
先上代码:
1. stack = [A],A拿出来检测,不该访问,于是stack = [A,C,B]
2. B拿出来检测,不该访问,于是stack = [A,C,B,E,D]
3. D拿出来检测,该访问,stack = [A,C,B,E],E拿出来检测,该访问,stack = [A,C,B],B拿出来检测,该访问,stack = [A,C],此时result = [D,E,B]
4. C拿出来检测,不该访问,stack = [A,C,G,F]
。。。后面的步骤我就不说了
其中,第26行是检测条件,需小心写。
感谢写出这篇博文的大神,确实思路相当清晰。好了,我到此也长出一口气,三种遍历的非递归算法总算写完了
前序遍历:点击打开链接
中序遍历:点击打开链接
好,回到已经用了三次的那张老图:
后序遍历的结果应该是:DEBFGCA
这也是三种遍历模型中最难的一个。因为要先访问左右两个孩子,再访问其父节点。如果按照以前的方法,类似地设计栈对数据流的巧妙控制,虽然最终也能做出来,但确实比较难。好在我查到一个博主的文章,他给出了一个更简单的方法。详见:点击打开链接
在此,我把这种方法再按我自己的理解,更简单地复述一遍:
我们在处理这棵树的时候,还是可以先建立一个栈,按照“根-右-左”的顺序依次将节点添加到栈,但是根据后序遍历的规则,我们现在并不能访问这些节点,什么时候可以了呢?当现在访问到的节点是叶子节点或者是回溯时到达的节点(例如,访问完D之后,访问E,之后回溯到B,那么B就是回溯时到达的节点,此时是应该被访输出的)
好了,再理一下思路,按照“根-右-左”的顺序添加节点到栈中(因为栈是先进后出,所以输出时,正好和后序遍历的策略是一致的),但是每次在添加节点之前都必须先检查这个节点(是不是叶子?是不是回溯的?)如果是,则访问该节点,输出值。
先上代码:
""" Definition of TreeNode: class TreeNode: def __init__(self, val): self.val = val self.left, self.right = None, None """ class Solution: """ @param root: The root of binary tree. @return: Postorder in ArrayList which contains node values. """ def postorderTraversal(self, root): result = [] stack = [] # 用pre记录上一次访问的节点,初始时为空 cur, pre = None, None if root: stack.append(root) while len(stack) != 0: # 取出栈顶节点,做检测 cur = stack[-1] # 只要满足:1. 是叶子;2. 是回溯的;其中之一,则访问 if cur.left == cur.right == None or (pre is not None and (pre == cur.left or pre == cur.right)): result.append(cur.val) stack.pop() pre = cur # 如果检测结果不满足上述两个条件,继续按照先右后左的顺序插入值 else: if cur.right: stack.append(cur.right) if cur.left: stack.append(cur.left) return result # write your code here现在来看看代码运行的情况,以上图为例,设栈为stack:
1. stack = [A],A拿出来检测,不该访问,于是stack = [A,C,B]
2. B拿出来检测,不该访问,于是stack = [A,C,B,E,D]
3. D拿出来检测,该访问,stack = [A,C,B,E],E拿出来检测,该访问,stack = [A,C,B],B拿出来检测,该访问,stack = [A,C],此时result = [D,E,B]
4. C拿出来检测,不该访问,stack = [A,C,G,F]
。。。后面的步骤我就不说了
其中,第26行是检测条件,需小心写。
感谢写出这篇博文的大神,确实思路相当清晰。好了,我到此也长出一口气,三种遍历的非递归算法总算写完了
相关文章推荐
- AVL树-自平衡二叉查找树(Java实现)
- C++基于栈实现铁轨问题
- C语言二叉树的非递归遍历实例分析
- C语言栈的表示与实现实例详解
- 使用C语言构建基本的二叉树数据结构
- C语言实现颠倒栈的方法
- 一波二叉树遍历问题的C++解答实例分享
- 举例讲解C语言程序中对二叉树数据结构的各种遍历方式
- C++非递归队列实现二叉树的广度优先遍历
- 算法系列15天速成 第十天 栈
- C#使用前序遍历、中序遍历和后序遍历打印二叉树的方法
- 一看就懂:图解C#中的值类型、引用类型、栈、堆、ref、out
- Array栈方法和队列方法的特点说明
- java数据结构之java实现栈
- 浅析栈区和堆区内存分配的区别
- C#非递归先序遍历二叉树实例
- C++将二叉树转为双向链表及判断两个链表是否相交
- C++非递归建立二叉树实例
- C语言实现找出二叉树中某个值的所有路径的方法
- C++实现二叉树遍历序列的求解方法