二叉树的后序遍历

本文介绍了二叉树后序遍历的非递归算法,通过建立一个栈,按照“根-右-左”的顺序添加节点,并在添加节点前检查是否为叶子节点或回溯节点以符合后序遍历规则。详细步骤和关键检测条件在文中阐述。
摘要由CSDN通过智能技术生成

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

前序遍历:点击打开链接

中序遍历:点击打开链接

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


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

感谢写出这篇博文的大神,确实思路相当清晰。好了,我到此也长出一口气,三种遍历的非递归算法总算写完了


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值