二叉树及N叉树的遍历

本文详细介绍了二叉树的前序、中序、后序和层序遍历的递归和迭代实现,以及N叉树的遍历方法,还涉及如何根据前序、中序或后序遍历序列构造二叉树。
摘要由CSDN通过智能技术生成

过年不卷、随便写点。

二叉树的遍历主要分为前中后序遍历加一个层序遍历。

前序遍历:中左右

中序遍历:左中右

后续遍历:左右中

层序遍历:从上到下,从左到右

前序遍历

两种方法:1.递归,简单  2.迭代,难一点

144. 二叉树的前序遍历

递归写法

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # 递归终止条件
        if not root:
            return []
        # 左
        left = self.preorderTraversal(root.left)
        # 右
        right = self.preorderTraversal(root.right)
        # 中左右,前序
        return [root.val] + left + right

迭代写法

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # 如果为空直接返回空列表
        if not root:
            return []
        # 栈
        stack = [root]
        # 保存结果
        res = []
        while stack:
            # 出栈
            node = stack.pop()
            if node:
                # 如果不为空,值入res
                res.append(node.val)
                # 栈先进后出,因为是前序,中左右,右子树先入栈,然后左子树入栈
                if node.right:
                    stack.append(node.right)
                if node.left:
                    stack.append(node.left)
        return res

中序遍历

递归写法94. 二叉树的中序遍历

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # 终止条件
        if not root:
            return []
        # 左
        left = self.inorderTraversal(root.left)
        # 右
        right = self.inorderTraversal(root.right)
        # 中序,左中右
        return left + [root.val] + right

迭代写法

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        cur = root
        stack = []
        res = []
        while cur or stack:
            # 先迭代访问左子树最底层的结点
            if cur:     
                stack.append(cur)
                cur = cur.left		
            # 到达最左结点后处理栈顶结点    
            else:		
                cur = stack.pop()
                res.append(cur.val)
                # 向右迭代
                cur = cur.right
        return res

后序遍历

左右中

145. 二叉树的后序遍历

递归没什么好说的,和前面几乎一样

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        if not root:
            return []
        left = self.postorderTraversal(root.left)
        right = self.postorderTraversal(root.right)
        return left + right + [root.val]

迭代写法

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        res = []
        stack = []
        if root:
            stack.append(root)
        while stack:
            node = stack.pop()
            if node != None:
                stack.append(node) #中
                # 中节点未处理,加入None作为标记
                stack.append(None)
                if node.right: #右,空节点不入栈
                    # 添加右节点
                    stack.append(node.right)
                if node.left: #左,空节点不入栈
                    # 添加左节点
                    stack.append(node.left)
            else:
                # 空的弹出
                node = stack.pop()
                # 加入结果集
                res.append(node.val)
        return res

层序遍历

从上到下,从左到右,广搜

102. 二叉树的层序遍历

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        if root is None:
            return []
        res = []
        cur = [root]
        while cur:
            # 初始化下一层
            next_level = []
            vals = []
            for node in cur:
                vals.append(node.val)
                # 从左到右
                if node.left:
                    next_level.append(node.left)
                if node.right:
                    next_level.append(node.right)
            # 下一层
            cur = next_level
            # 加入结果
            res.append(vals)
        return res

过年一直是二叉树!!另一种层序遍历(从下到上)

层序遍历变体

107. 二叉树的层序遍历 II

和层序遍历类似,返回的时候翻转顺序即可

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def levelOrderBottom(self, root: Optional[TreeNode]) -> List[List[int]]:
        if not root:
            return []
        stack = [root]
        res = []
        while stack:
            next_level = []
            vals = []
            for node in stack:
                vals.append(node.val)
                if node.left:
                    next_level.append(node.left)
                if node.right:
                    next_level.append(node.right)
            stack = next_level
            res.append(vals)
        # 返回时反转顺序
        return res[::-1]

垂序遍历

这是真的听的少,就做题时候看到的

987. 二叉树的垂序遍历

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
        # 队列,根节点
        queue = collections.deque([[root, 0, 0]])
        hashmap = collections.defaultdict(list)
        # 遍历队列先进先出,j=列 i=行 先列后行是因为垂序遍历的顺序是从左列到右列,从上行到下行
        while queue:
            node, j, i = queue.popleft()
            # 对应位置(j,i)加入当前节点值
            hashmap[(j, i)].append(node.val)
            # 判断有无左孩子
            if node.left:
                queue.append([node.left, j-1, i+1])
            # 判断有无右孩子
            if node.right:
                queue.append([node.right, j+1, i+1])
        
        res = []
        temp = []
        # j_flag 是初始化值,在节点数范围外
        j_flag = -1001
        for j, i in sorted(hashmap.keys()):
            # 不同列
            if j != j_flag:
                res.append(temp)
                temp = []
                j_flag = j 
            # 将排完序的hashmap扩展到temp中,
            temp.extend(sorted(hashmap[(j, i)]))
        # 第一个是空的弹出
        res.pop(0)
        # 最后一个temp没加入,最后加入
        res.append(temp)
        return res

N叉树的层序遍历

之前都是二叉,现在是N叉的层序遍历

429. N 叉树的层序遍历

"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""

class Solution:
    def levelOrder(self, root: 'Node') -> List[List[int]]:
        if not root:
            return []
        res = []
        queue = deque([root])
        while queue:
            vals = []
            for _ in range(len(queue)):
                node = queue.popleft()
                vals.append(node.val)
                queue.extend(node.children)
            res.append(vals)
        return res

和二叉树的层序遍历没有什么区别。

N叉树的前序遍历

589. N 叉树的前序遍历

"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""

class Solution:
    def preorder(self, root: 'Node') -> List[int]:
        stack = []
        res = []
        if root:
            stack.append(root)
        while stack:
            node = stack.pop()
            if node:
                res.append(node.val)
                for child in node.children[::-1]:
                    stack.append(child)
        return res
        

N叉树的后序遍历

590. N 叉树的后序遍历

"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""

class Solution:
    def postorder(self, root: 'Node') -> List[int]:
        res = []
        stack = []
        if root:
            stack.append(root)
        while stack:
            p = stack.pop()
            stack.extend(p.children)
            res.append(p.val)
        return res[::-1]

当你了解了什么是前序遍历,什么是中序遍历,什么是后续遍历,任何根据遍历生成树呢?

生成二叉树

根据前序中序构造二叉树

105. 从前序与中序遍历序列构造二叉树

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
        # 105/106类似
        # 第一步: 特殊情况讨论: 树为空. 或者说是递归终止条件
        if not preorder:
            return None

        # 第二步: 前序遍历的第一个就是当前的中间节点.
        root_val = preorder[0]
        root = TreeNode(root_val)

        # 第三步: 找切割点.
        separator_idx = inorder.index(root_val)

        # 第四步: 切割inorder数组. 得到inorder数组的左,右半边.
        inorder_left = inorder[:separator_idx]
        inorder_right = inorder[separator_idx + 1:]

        # 第五步: 切割preorder数组. 得到preorder数组的左,右半边.
        # 中序数组大小一定跟前序数组大小是相同的.
        preorder_left = preorder[1:1 + len(inorder_left)]
        preorder_right = preorder[1 + len(inorder_left):]

        # 第六步: 递归
        root.left = self.buildTree(preorder_left, inorder_left)
        root.right = self.buildTree(preorder_right, inorder_right)
        # 第七步: 返回答案
        return root


106. 从中序与后序遍历序列构造二叉树

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
        if not postorder:
            return None
        root_val = postorder[-1]
        root = TreeNode(root_val)

        mid_index = inorder.index(root_val)
        inorder_left = inorder[:mid_index]
        inorder_right = inorder[mid_index+1:]
        postorder_left = postorder[:len(inorder_left)]
        postorder_right = postorder[len(inorder_left):-1]
        root.left = self.buildTree(inorder_left, postorder_left)
        root.right = self.buildTree(inorder_right, postorder_right)
        return root
根据前序后续构造二叉树

889. 根据前序和后序遍历构造二叉树

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def constructFromPrePost(self, preorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
        if not preorder:
            return None
        if len(preorder) == 1:
            return TreeNode(preorder[0])
        
        root_val = preorder[0]
        root = TreeNode(root_val)

        pos_index = postorder.index(preorder[1]) + 1 
        preorder_left = preorder[1:1+pos_index]
        preorder_right = preorder[1+pos_index:]
        postorder_left = postorder[:len(preorder_left)]
        postorder_right = postorder[len(preorder_left):-1]
        root.left = self.constructFromPrePost(preorder_left, postorder_left)
        root.right = self.constructFromPrePost(preorder_right, postorder_right)
        return root

思路和之前一样,终止条件:1.如果前序为空,return None 2. 如果前序长度为1,则直接返回节点,preorder的第一个,postorder的最后一个为根节点。pos_index 为左子树的长度,分割preorder的左子树和右子树,分割postorder的左子树和右子树,然后分别左子树递归,右子树递归,返回根节点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值