leetcode-145-二叉树的后序遍历

题目描述

给你二叉树的根节点 root ,返回它节点值的 后序 遍历。

实例1:
输入:root = [1,null,2,3]
输出:[3,2,1]

提示

树中节点数目在范围 [0, 100] 内
-100 <= Node.val <= 100

思路

前序遍历的步骤是:

  • 访问根节点。
  • 根节点入栈。
  • 访问左子树。
  • 回到根节点。
  • 根节点出栈。
  • 访问右子树。

接下来采用递归形式和非递归形式进行实现。
非递归形式比较麻烦。
在非递归中有一点值得注意,就是在访问根节点的条件,如下

  • 叶子节点。
  • 根的右子节点是上一次访问的节点,并且由于后序遍历的特点,栈顶节点并非上一次访问的节点,需要借助一个prev变量记录上一次访问的节点。

解决

后序遍历-递归形式

    # 递归形式。
    def postorderTraversal(self, root: TreeNode) -> list[int]:
        res_list = []

        # 递归函数。
        def postorder(root, p_list):
            if root:
                # 访问左子树。
                postorder(root.left, p_list)
                # 访问右子树。
                postorder(root.right, p_list)
                # 访问根节点。
                p_list.append(root.val)

        postorder(root, res_list)
        return res_list

后序遍历-非递归形式

    # 后序遍历:左子树-右子树-根。
    # 实现步骤:根节点入栈-访问左子树-返回根节点-访问右子树-返回根节点-访问根节点-根节点出栈。
    """
    其中访问节点的类型:
    1、当前经过节点是叶子节点。
    2、当前经过节点的右子节点是上一次访问的节点。
    """
    # 非递归形式。
    def postorderTraversal(self, root: TreeNode) -> list[int]:
        stack_list = []
        res_list = []
        p = root
        # 用于记录上一次访问的节点,和前序遍历不同,其栈中上一个节点并非上一次访问的。
        prev = None
        while p or len(stack_list) > 0:
            while p:
                # 根节点入栈。
                stack_list.append(p)
                # 访问左子树。
                p = p.left
            if len(stack_list) > 0:
                # 返回根节点。
                p = stack_list.pop(-1)
                # 判别 右子树 是否访问。
                # 判断条件:当前节点p 为 其父节点 右孩子。
                if not p.right or p.right == prev:
                    # 已访问右子树,返回根节点,访问根节点,根节点出栈。
                    res_list.append(p.val)
                    prev = p
                    # 此处为了跳过下一次循环的访问左子节点的过程,直接进入栈的弹出阶段,因为但凡在栈中的节点,它们的左子节点都肯定被经过且已放入栈中。
                    p = None
                else:
                    # 不访问节点,则弹回节点。
                    stack_list.append(p)
                    # 访问右子树。
                    p = p.right
        return res_list

结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值