Skip to main content

Command Palette

Search for a command to run...

二叉树的遍历

Updated
2 min read
二叉树的遍历

掌握两种方法进行二叉树的遍历,这里重点看迭代法是怎么写,迭代法使用栈来模拟递归中的栈,也可以使用一种通用方式进行前、中、后序遍历。

递归法

def dfs(root) {
    // 前序遍历
    dfs(root.left)
    // 中序遍历
    dfs(root.right)
    // 后序遍历
}

迭代法:迭代法是用 stack 栈来模拟递归栈

下面这种写法可以统一前序、中序、后序遍历方式的写法,只需要改变入栈顺序

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

中序遍历:
栈是一种 先进后出的结构,出栈顺序为左,中,右
那么入栈顺序必须调整为倒序,也就是右,中,左

同理,如果是前序遍历,入栈顺序为 右,左,中;后序遍历,入栈顺序 中,右,左

有没有发现?迭代法入栈顺序与递归法的递归顺序正好相反!

while stack:
    node = stack.pop()
    if node == None:
        continue
    if isinstance(node, int):
        ans.append(node)
    else:
        # 中序遍历
        stack.extend([node.right, node.val, node.left])
        # 前序遍历
        # stack.extend([node.right, node.left, node.val])
        # 后序遍历
        # stack.extend([node.val, node.right, node.left])
  • 每个节点都只入栈一次,出栈一次

中序遍历

94. 二叉树的中序遍历

递归法:

class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        ans = []

        def dfs(root):
            if root == None:
                return
            dfs(root.left)
            ans.append(root.val)
            dfs(root.right)
        dfs(root)
        return ans

迭代法:迭代法是用 stack 栈来模拟递归栈

class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        ans = []
        stack = [root]
        while stack:
            node = stack.pop()
            if node == None:
                continue
            if isinstance(node, int):
                ans.append(node)
            else:
                stack.extend([node.right, node.val, node.left])
        return ans

前序遍历

递归

class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        ans = []
        def dfs(root):
            if root==None:
                return
            ans.append(root.val)
            dfs(root.left)
            dfs(root.right)
        dfs(root)
        return ans

迭代

class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        ans = []
        stack = [root]
        while stack:
            node = stack.pop()
            if node == None:
                continue
            if isinstance(node, int):
                ans.append(node)
            else:
                stack.extend([node.right, node.left, node.val])
        return ans

后序遍历

145. 二叉树的后序遍历

递归

class Solution:
    def postorderTraversal(self,root:Optional[TreeNode])->List[int]:
        ans= []
        def dfs(root):
            if root==None:
                return
            dfs(root.left)
            dfs(root.right)
            ans.append(root.val)
        dfs(root)
        return ans

迭代

class Solution:
    def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        ans = []
        stack = [root]
        while stack:
            node = stack.pop()
            if node == None:
                continue
            if isinstance(node, int):
                ans.append(node)
            else:
                stack.extend([node.val, node.right, node.left])
        return ans

层次遍历

层次遍历需要借助队列进行层次遍历

class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        if root == None:
            return []
        ans = []
        q = deque([root])
        while q:
            floor = []
            for _ in range(len(q)):
                node = q.popleft()
                floor.append(node.val)
                if node.left:
                    q.append(node.left)
                if node.right:
                    q.append(node.right)
            ans.append(floor)
        return ans

More from this blog

根据前、中、后序数组构造二叉树

根据两个遍历数组生成二叉树,主要是固定住一个根节点,然后去另一个数组查找下标,划分数组做左右子树,再递归执行左子树和右子树。 这里主要讨论的是使用切片的过程中如何确定切片的起始点,即切片的区间,利用的是左子树的长度。 前序和中序构造二叉树 105. 从前序与中序遍历序列构造二叉树 递归加切片, python 中可以使用 index 函数直接获取值的下标。 注意:切片是左闭右开区间,最后一个值取不到 切片的下标如何思考:利用左子树的长度来辅助思考。idx 是中序数组中的当前节点下标,所以左子...

Apr 3, 20242 min read
根据前、中、后序数组构造二叉树

函数式编程在 Java 和 Go 中的应用

函数式编程是一种 "编程范式"(programming paradigm),就是如何编写程序的方法论。 函数式编程特点: 函数是"第一等公民" 只用"表达式",不用"语句" "表达式"(expression)是一个单纯的运算过程,总是有返回值;"语句"(statement)是执行某种操作,没有返回值。函数式编程要求,只使用表达式,不使用语句。也就是说,每一步都是单纯的运算,而且都有返回值。 没有"副作用" 所谓"副作用"(side effect),指的是函数内部与外部互动(最典型的情况,就...

Jun 26, 20237 min read
函数式编程在 Java 和 Go 中的应用

Untitled Publication

13 posts