• 二叉树的遍历


    1 递归遍历

    写法类似于回溯,前序 中序 后序遍历的套路一样,只是保存元素的位置不同.层序遍历的关键是要添加level参数,用于记录节点所在的层数.

    class TreeNode:
        def __init__(self, x):
            self.val = x
            self.left = None
            self.right = None
    # 经典的递归法
    from typing import List
    class Solution:
        def inorderTraversal(self, root: TreeNode) -> List[int]:
            result_pre = []
            result_in = []
            result_bac = []
            def recursion(root):
                # 如果遍历到一个分支的底了,则为空节点,返回True,继续遍历
                if root == None:
                    return
                # 前序遍历
                result_pre.append(root.val)
                recursion(root.left)
                # 中序遍历
                result_in.append(root.val)
                recursion(root.right)
                # 后序遍历
                result_bac.append(root.val)
            recursion(root)
            print(result_pre)
            print(result_in)
            print(result_bac)
    
    # 这里的层序遍历是dfs,深度优先遍历
    class Solution:
        def levelOrder(self, root):
            levels = []
            # 如果为空节点,直接返回[]
            if not root:
                return levels
            def helper(node, level):
                # 如果相等了,说明是新加的层,则添一个[]
                if len(levels) == level:
                    levels.append([])
                # 将节点存入相应的层
                levels[level].append(node.val)
                # 注意必须是先左后右,这样才能保证每层是按从左往右顺序存储的
                if node.left:
                    helper(node.left, level + 1)
                if node.right:
                    helper(node.right, level + 1)
            helper(root, 0)
            return levels
    
    if __name__ == '__main__':
        duixiang = Solution()
        root = TreeNode(8)
        a = TreeNode(4)
        b = TreeNode(9)
        root.left = a
        root.right = b
    
        al = TreeNode(3)
        ar = TreeNode(6)
        a.left = al
        a.right = ar
    
        arl = TreeNode(5)
        arr = TreeNode(7)
        ar.left = arl
        ar.right = arr
    
        a = duixiang.levelOrder(root)
        print(a)
    View Code

    2 迭代遍历

    中序和后序遍历比前序遍历思路一样,只不过多了对节点的记录,没有遍历过标记为1,等待遍历,遍历过的标记为0.

    class TreeNode:
        def __init__(self, x):
            self.val = x
            self.left = None
            self.right = None
    # 前序遍历的迭代法
    class Solution:
        def preorder(self, root):
            res = []
            if root is None:
                return []
            stack = []
            stack.append(root)
            # 只有前序遍历可以这样写,因为前序遍历先存储中间的节点值,是中 左 右的顺序遍历
            # 而中序和后序遍历需要从最左边开始,而我们是从最上面的节点开始遍历的,所以需要记录节点是否被遍历过
            while stack:
                x = stack.pop()
                res.append(x.val)
                if x.right:
                    stack.append(x.right)
                if x.left:
                    stack.append(x.left)
            return res
    # 层序遍历的迭代法
    class Solution:
        def levelOrder(self, root: TreeNode) -> List[List[int]]:
            results = []
            stack_next = []
            if not root:
                return []
            stack_next.append(root)
            # stack_next用于记录下一层的节点,stack用于遍历当前层
            while stack_next:
                stack = stack_next
                # 记录节点前先清空
                stack_next = []
                res = []
                while stack:
                    # 由于每一层都是从左往右依次保存,故这里用队列
                    k = stack.pop(0)
                    # 注意这里的顺序
                    if k.left:
                        stack_next.append(k.left)
                    if k.right:
                        stack_next.append(k.right)
                    res.append(k.val)
                # 下次循环res被赋值为空了,为新的引用,故不用深拷贝也行
                results.append(res)
            return results
    # 中序后序遍历的迭代法
    class Solution:
        def levelOrder(self, root):
            res = []
            stack = []
            stack.append((root,1))
            while stack:
                x,sign = stack.pop()
                if x is None:
                    continue
                # 这里用0标记被遍历过了,1表示没有遍历,如遍历过了则存储
                # 否则继续遍历,一直朝左找到底
                if sign:
                    # 中序遍历
                    stack.append((x.right, 1))
                    stack.append((x, 0))
                    stack.append((x.left,  1))
                    ## 后序遍历
                    # stack.append((x, 0))
                    # stack.append((x.right, 1))
                    # stack.append((x.left,  1))
                else:
                    res.append(x.val)
            return res
    if __name__ == '__main__':
        duixiang = Solution()
        root = TreeNode(8)
        a = TreeNode(4)
        b = TreeNode(9)
        root.left = a
        root.right = b
    
        al = TreeNode(3)
        ar = TreeNode(6)
        a.left = al
        a.right = ar
    
        arl = TreeNode(5)
        arr = TreeNode(7)
        ar.left = arl
        ar.right = arr
    
        a = duixiang.levelOrder(root)
        print(a)
    View Code

    中序遍历的迭代实现,这个方法非常精妙,充分利用了中序遍历的结构特点,每个节点都是进一次栈出一次栈.

    # # 中序遍历的迭代方法
    # https://leetcode.com/problems/binary-tree-inorder-traversal/discuss/442853/Python-recursion-simple-and-readable-beat-90.22-runtime-100-memory
    from typing import List
    class Solution:
        def levelOrder(self, root: TreeNode) -> List[int]:
            res,temp = [],[]
            while 1:
                # 先对某个节点超左遍历到底,
                while root:
                    temp.append(root)
                    root = root.left
                # 栈为空,说明遍历完了,返回结果
                if not temp:return res
                # 然后一个一个弹出来,
                root = temp.pop()
                res.append(root.val)
                # 每弹出一个来,都要判断其是否有右子树,如果有继续压栈遍历
                # 事实上这里只有两种情况,如果左边的root为空了,说明右边的root为左 中 右的左,否则为中,
                root = root.right
    View Code

    后序遍历的迭代实现,前序遍历是中 左 右,后序是左 右 中,反过来是中 右 左,利用对称性只需在前序遍历的基础上稍微改动即可.

    class Solution:
        def postorderTraversal(self, root: TreeNode) -> List[int]:
            stack,res = [],[]
            if root is None:
                return []
            stack.append(root)
            while stack:
                a = stack.pop()
                res.append(a.val)
                if a.left:
                    stack.append(a.left)
                if a.right:
                    stack.append(a.right)
            res.reverse()
            return res
    View Code
  • 相关阅读:
    Android最佳性能实践(二)——分析内存的使用情况
    Android最佳性能实践(一)——合理管理内存
    Java反射机制
    Java基础知识总结之IO流
    Java之IO流详解
    CentOS 6.4安装中文支持
    because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'style-src' was not explicitly set, so 'default-src' is used as a fallback.错误应该怎么解决?
    在asp.net添加引用Microsoft.VisualBasic全过程
    SQL SERVER 2012安装介质
    Microsoft SQL Server附加数据库错误:5123
  • 原文地址:https://www.cnblogs.com/xxswkl/p/11995665.html
Copyright © 2020-2023  润新知