您的位置:首页 > 其它

二叉树的后序遍历

2016-04-15 12:49 190 查看
这是二叉树的三种主要遍历方式的最后一种了,前面两种我们已经讨论过,后序遍历其实就是将策略转换成了"左-右-根",其他方面跟前两种一样,都是深搜的逻辑。前两种详见以下链接:

前序遍历:点击打开链接

中序遍历:点击打开链接

好,回到已经用了三次的那张老图:



后序遍历的结果应该是: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行是检测条件,需小心写。

感谢写出这篇博文的大神,确实思路相当清晰。好了,我到此也长出一口气,三种遍历的非递归算法总算写完了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二叉树