二叉树的后序遍历是一种重要的树遍历方式,其访问顺序是:先遍历左子树,再遍历右子树,最后访问根节点

后序遍历是一种访问顺序规则,而非递归算法是实现这种顺序的一种方式。它们的区别可以从两个层面理解:


✅ 1. 定义 vs 实现

项目后序遍历非递归算法
本质一种访问顺序(左 → 右 → 根)一种实现方式(用栈代替递归)
是否具体算法否,是规则是,是代码实现
是否唯一实现方式否,可用递归或非递归否,也可用递归

✅ 2. 递归 vs 非递归:实现方式对比

对比维度递归实现非递归实现
代码结构简洁,利用函数调用栈复杂,需手动维护栈
空间复杂度依赖系统调用栈,最坏 O(n)手动栈,最坏 O(n)
可读性
适用语言所有支持递归的语言所有语言(尤其适合不支持递归或栈深度受限的环境)
调试难度递归栈深时难调试手动栈逻辑复杂,易出错

✅ 举个例子

假设有一棵二叉树:

    A
   / \
  B   C
 / \
D   E
  • 后序遍历顺序:D → E → B → C → A
  • 这个顺序可以用递归实现(简洁),也可以用非递归栈实现(更底层)

✅ 总结一句话

“后序遍历”是规则,“非递归算法”是用栈实现这个规则的一种方式。

二叉树的后序遍历是一种重要的树遍历方式,其访问顺序是:先遍历左子树,再遍历右子树,最后访问根节点。

以下是实现二叉树后序遍历的 Python 代码,包含了递归和迭代两种常见方法:

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    # 递归实现后序遍历
    def postorderTraversalRecursive(self, root: TreeNode) -> list[int]:
        result = []
        
        def helper(node):
            if not node:
                return
            # 先遍历左子树
            helper(node.left)
            # 再遍历右子树
            helper(node.right)
            # 最后访问根节点
            result.append(node.val)
            
        helper(root)
        return result
    
    # 迭代实现后序遍历
    def postorderTraversalIterative(self, root: TreeNode) -> list[int]:
        if not root:
            return []
        
        result = []
        stack = []
        prev = None
        
        while root or stack:
            # 遍历到最左子节点
            while root:
                stack.append(root)
                root = root.left
            
            # 取出栈顶节点
            root = stack.pop()
            
            # 如果右子树为空或已访问过,则访问当前节点
            if not root.right or root.right == prev:
                result.append(root.val)
                prev = root
                root = None
            else:
                # 否则将当前节点重新入栈,处理右子树
                stack.append(root)
                root = root.right
        
        return result

# 示例用法
if __name__ == "__main__":
    # 构建一个示例二叉树
    #       1
    #        \
    #         2
    #        /
    #       3
    root = TreeNode(1)
    root.right = TreeNode(2)
    root.right.left = TreeNode(3)
    
    solution = Solution()
    print("递归后序遍历结果:", solution.postorderTraversalRecursive(root))  # 输出: [3, 2, 1]
    print("迭代后序遍历结果:", solution.postorderTraversalIterative(root))  # 输出: [3, 2, 1]

代码解析:

  1. 首先定义了TreeNode类来表示二叉树的节点,每个节点包含值、左子节点和右子节点。

  2. 递归实现:

    • 使用辅助函数helper进行递归
    • 递归遍历左子树,再递归遍历右子树,最后将当前节点的值加入结果列表
    • 递归方法简洁直观,符合后序遍历的定义
  3. 迭代实现:

    • 使用栈来模拟递归过程
    • 先遍历到最左子节点,然后处理节点
    • 通过prev指针记录上一个访问的节点,用于判断右子树是否已访问
    • 当右子树为空或已访问时,才访问当前节点

两种方法都能得到相同的遍历结果,对于示例中的二叉树,后序遍历结果为[3, 2, 1]。递归方法代码简洁但可能受到递归深度限制,迭代方法则避免了这个问题。

二叉树的后序遍历

后序遍历(Postorder Traversal)是指按照以下顺序访问二叉树的节点:

  1. 首先遍历左子树;
  2. 然后遍历右子树;
  3. 最后访问根节点。

后序遍历的递归算法:

void PostOrder(BiTree T) {
    if (T != NULL) {
        PostOrder(T->lchild);   // 遍历左子树
        PostOrder(T->rchild);   // 遍历右子树
        printf("%c", T->data);  // 访问根节点
    }
}

后序遍历的非递归算法(使用栈):

void PostOrder(BiTree T) {
    SqStack S;
    BiTNode *p = T;
    BiTNode *r = NULL;  // 标记最近访问的节点
    InitStack(S);
    
    while (p != NULL || !StackEmpty(S)) {
        if (p != NULL) {  // 走到最左边
            Push(S, p);
            p = p->lchild;
        } else {
            GetTop(S, p);  // 读栈顶节点
            if (p->rchild != NULL && p->rchild != r) {
                p = p->rchild;  // 转向右子树
                Push(S, p);
                p = p->lchild;
            } else {
                Pop(S, p);     // 弹出并访问节点
                printf("%c", p->data);
                r = p;         // 记录最近访问的节点
                p = NULL;
            }
        }
    }
}

返回图片

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bol5261

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值