二叉树的遍历

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

 

posted on 2019-12-06 15:43  吃我一枪  阅读(215)  评论(0编辑  收藏  举报

导航