我是靠谱客的博主 高高篮球,最近开发中收集的这篇文章主要介绍二叉树非递归三种遍历的统一模板,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

今天在LeetCode刷题的时候,遇到一个二叉树非递归后序遍历的题目。
评论区发现一位大神给的前中后序都通用的非递归模板,着实受益匪浅,因此记录一下。

原文参见:https://leetcode-cn.com/problems/binary-tree-postorder-traversal/solution/mo-fang-di-gui-zhi-bian-yi-xing-by-sonp/
用C++写的,这里我改成了Python。

二叉树结点的定义如下:
from typing import List


# Definition for a binary tree node.

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
后序遍历的模板代码

首先应该说清楚的是:除了前序遍历外,对结点的首次访问和对结点的处理并不是同时发生的,后两者对结点的处理发生在第二次访问时——例如中序遍历,每个结点首次访问到之后,还会去访问它的左子树,直至左子树全部访问完毕再次回到这个结点,才是对当前结点的访问/处理。
因此有必要标识清楚当前是对结点的第几次访问 ——
以上就是下面的代码中结点压入栈的时候要额外让None进栈的原因,遇到None则对其下一个结点进行处理 。

(吐槽一下,Python代码注释的字体好丑……)

class Solution:
    def postorderTraversal(self, root: TreeNode) -> List[int]:
        res = []  # 储存遍历结果
        stack = []  # 模拟栈
        if root:
            stack.append(root)  # 根结点进栈保证循环正常进行,同时可以处理空树while stack:
​            t = stack.pop()  # 每一步拿出一个点if t:
                # 模拟递归的压栈顺序
​                stack.append(t)  # 顺着访问,因此逆着压栈,后序遍历是左右根,就先进根
​                stack.append(None)  # None用来表示下个结点从栈里面弹出来已经是第二次访问了if t.right:
​                    stack.append(t.right)  # 保证非空再进右if t.left:
​                    stack.append(t.left)  # 保证非空再进左else:  # 在第二次访问的时候,弹栈,对弹出的元素进行处理
​                res.append(stack.pop().val)  # 此处可以写对当前结点进行任何处理的代码

        # 对于前序遍历,只要把根左右的遍历顺序逆向——右左根,把对应的代码顺序调整一下即可
        # 中序遍历也是如此——右根左
        # 最后提一句,因为前序遍历首次访问和对节点的处理是同时发生的,因此代码可以简化return res
完整非递归后序遍历代码

下面贴一个可以直接运行的代码,方便理清思路和调试。

from typing import List


# Definition for a binary tree node.
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None


class Solution:
    def postorderTraversal(self, root: TreeNode) -> List[int]:
        res = []
        stack = []
        if root:
            stack.append(root)

        while stack:
            t = stack.pop()
            if t:
                stack.append(t)  # 1
                stack.append(None)  # 1
                if t.right:  # 2
                    stack.append(t.right)
                if t.left:  # 3
                    stack.append(t.left)
                # 对于前序遍历和中序遍历,调整# 1的顺序即可
                # 把#1 放在#2与#3之间就是中序遍历
                # 把#1 放在#3之后就是前序遍历
            else:
                res.append(stack.pop().val)

        return res


if __name__ == '__main__':
    # 构造下面的一棵二叉树
    #           1
    #         /   
    #        2     3
    #         
    #          4
    r = TreeNode(1)
    r.left = TreeNode(2)
    r.right = TreeNode(3)
    r.left.right = TreeNode(4)

    # 后序遍历
    solution = Solution()
    post_order = solution.postorderTraversal(r)
    print(post_order)
对应的前序遍历与中序遍历

前序遍历只要将后序遍历中“根右左”的顺序调整为对应的“右左根”即可:

# 前序遍历中 if t: 内的代码调整为如下格式即可。
    if t.right:
        stack.append(t.right)
    if t.left:
        stack.append(t.left)
    stack.append(t)
    stack.append(None)

中序遍历大家可以自己试试~

最后

以上就是高高篮球为你收集整理的二叉树非递归三种遍历的统一模板的全部内容,希望文章能够帮你解决二叉树非递归三种遍历的统一模板所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部