代码随想录Day14|递归遍历、迭代遍历、统一遍历

目录

理论基础

递归遍历 

        144. 二叉树的前序遍历

      94. 二叉树的中序遍历

           145. 二叉树的后序遍历 

迭代遍历

        前序遍历

         后序遍历

        中序遍历

统一遍历


理论基础

代码随想录 (programmercarl.com)

二叉树主要有两种遍历方式:

  1. 深度优先遍历:先往深走,遇到叶子节点再往回走。
  2. 广度优先遍历:一层一层的去遍历。

这两种遍历是图论中最基本的两种遍历方式,后面在介绍图论的时候 还会介绍到。

那么从深度优先遍历和广度优先遍历进一步拓展,才有如下遍历方式:

  • 深度优先遍历
    • 前序遍历(递归法,迭代法)
    • 中序遍历(递归法,迭代法)
    • 后序遍历(递归法,迭代法)
  • 广度优先遍历
    • 层次遍历(迭代法)

在深度优先遍历中:有三个顺序,前中后序遍历, 有同学总分不清这三个顺序,经常搞混,我这里教大家一个技巧。

这里前中后,其实指的就是中间节点的遍历顺序,只要大家记住 前中后序指的就是中间节点的位置就可以了。

看如下中间节点的顺序,就可以发现,中间节点的顺序就是所谓的遍历方式

  • 前序遍历:中左右
  • 中序遍历:左中右
  • 后序遍历:左右中

递归遍历 

 图解 二叉树的四种遍历 - 二叉树的前序遍历 - 力扣(LeetCode)

由于层次遍历的递归解法不是主流,因此只介绍前三种的递归解法。它们的模板相对比较固定,一般都会新增一个 dfs 函数

对于前序、中序和后序遍历,只需将递归函数里的 res.append(root.val) 放在 不同位置 即可,然后调用这个递归函数就可以了,代码完全一样。

        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]:
        res = []
        def dfs(root):
            if not root:
                return []
            
            res.append(root.val)    # 将根节点值加入结果
            dfs(root.left)          # 左
            dfs(root.right)         # 右
        dfs(root)
        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 preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        res = []
        def dfs(root):
            if not root:
                return []

            dfs(root.left)          # 左
            res.append(root.val)    # 将根节点值加入结果
            dfs(root.right)         # 右
        dfs(root)
        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 preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        res = []
        def dfs(root):
            if not root:
                return []

            dfs(root.left)          # 左
            dfs(root.right)         # 右
            res.append(root.val)    # 将根节点值加入结果
        dfs(root)
        return res

迭代遍历

        前序遍历

        前序遍历是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。

        为什么要先加入 右孩子,再加入左孩子呢? 因为这样出栈的时候才是中左右的顺序。

# 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, res = [root], []
        while stack:
            node = stack.pop()
            if node:
                res.append(node.val)    # 根节点加入到结果中
                if node.right:          # 右子树入栈
                    stack.append(node.right)
                if node.left:           # 左子树入栈
                    stack.append(node.left)
        return res

         后序遍历

        在前序遍历的基础上,将左右的顺序调整一下变成中右左,最后在将数组翻转就变成了左右中。

# 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 []
        stack, res = [root], []
        while stack:
            node = stack.pop()
            if node:
                res.append(node.val)    # 根节点加入到结果中
                if node.left:           # 左子树入栈
                    stack.append(node.left)
                if node.right:          # 右子树入栈
                    stack.append(node.right)
        
        return res[::-1]

        中序遍历

         先把根节点和所有的左孩子放到栈中,当cur为空时,开始弹出元素放入res中,弹出元素后,取他的右孩子当做cur放到栈中。知道栈为空结束循环

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return []
        stack = []  # 不能提前将root结点加入stack中
        result = []
        cur = root
        while cur or stack:
            # 先迭代访问最底层的左子树结点
            if cur:     
                stack.append(cur)
                cur = cur.left		
            # 到达最左结点后处理栈顶结点    
            else:		
                cur = stack.pop()
                result.append(cur.val)
                # 取栈顶元素右结点
                cur = cur.right	
        return result

统一遍历

你可能感兴趣的:(算法)