Python Leetcode刷题之二叉树遍历

博客主要介绍二叉树的四种遍历方式,包括前序、中序、后序和层序遍历。详细阐述了每种遍历方式的顺序及结果,并给出了递归和迭代的实现方法。其中,前三种遍历采用深度优先搜索,层序遍历使用广度优先搜索,还说明了不同遍历方式迭代实现的具体步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二叉树

二叉树的遍历主要有前序、中序、后序、层序四种遍历方式,遍历方法可以通过递归和迭代实现。

# 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

二叉树
如图,前序遍历按照根节点->左孩子->右孩子的方式遍历,因此遍历结果为:1-2-4-5-3-6-7;
中序遍历按照左孩子->根节点->右孩子的方式遍历,因此遍历结果为:4-2-5-1-6-3-7;
后序遍历按照左孩子->右孩子->根节点的方式遍历,因此遍历结果为:4-5-2-6-7-3-1;
层序遍历按照每一层从左向右的方式进行遍历,因此遍历结果为:1-2-3-4-5-6-7;

1.二叉树的前序遍历

  • 递归实现
class Solution:
    def preorderTraversal(self, root: TreeNode) -> List[int]:
        res = []
        def presearch(root):
        	nonlocal res
            if not root:
                return 
            res.append(root.val)         #前序遍历
            presearch(root.left)
            presearch(root.right)
        presearch(root)
        return res
  • 迭代实现
    常规的迭代主要是通过栈来进行迭代,过程如下:

    1.初始化栈,并将根节点入栈;
    2.当栈不为空时:弹出栈顶元素node,并将值添加到结果中;如果node的右子树非空,将右子树入栈;如果node的左子树非空,将左子树入栈。(栈的先进后出原则)

class Solution:
    def preorderTraversal(self, root: 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

也可以用模板解法,模板解法先将根节点node和所有左孩子入栈并加入结果中,直至node为空(while循环),然后每弹出一个栈顶元素tmp,就到达它的右孩子,再将这个节点当作当前的node,重复上述操作,直至栈为空(while循环)

class Solution:
    def preorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return 
        stack, node, res = [], root, []
        while stack or node:
            while node:       #根节点和左孩子全部入栈
                res.append(node.val)
                stack.append(node)
                node = node.left
            tmp = stack.pop()       #每弹出一个元素,就到达右孩子
            node = tmp.right
        return res

2.二叉树的中序遍历

  • 递归实现
class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        res = []
        def midsearch(root):
            nonlocal res
            if not root:
                return 
            midsearch(root.left)
            res.append(root.val)        #中序遍历
            midsearch(root.right)
        midsearch(root)
        return res
  • 迭代实现

与前序遍历的代码一致,只是在出栈的时候才将节点tmp的值加入到结果中。

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return 
        stack, node, res = [], root, []
        while stack or node:
            while node:        #所有根节点和左孩子入栈,此时不计入res中
                stack.append(node)
                node = node.left
            tmp = stack.pop()
            res.append(tmp.val)      #弹出的节点加入到res中
            node = tmp.right 
        return res

3.二叉树的后序遍历

  • 递归实现
class Solution:
    def postorderTraversal(self, root: TreeNode) -> List[int]:
        res = []
        def postsearch(root):
            nonlocal res
            if not root:
                return 
            postsearch(root.left)
            postsearch(root.right)
            res.append(root.val)      #后序遍历
        postsearch(root)
        return res
  • 迭代实现
    利用后序遍历结果与前序遍历(根节点->右孩子->左孩子)结果输出相反的特性,迭代遍历可写成如下:
class Solution:
    def postorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return 
        stack, node, res = [], root, []
        while stack or node:
            while node:      #所有根节点和右孩子加入栈中
                stack.append(node)
                res.append(node.val)
                node = node.right
            tmp = stack.pop()    #弹出栈顶元素,访问左孩子
            node = tmp.left
        return res[::-1]

常规解法:
类比前序遍历的常规解法,我们只需要将输出的“根 -> 左 -> 右”的顺序改为“左 -> 右 -> 根”就可以了。

class Solution:
	def postorderTraversal(self, root: TreeNode) -> List[int]:
		if not root:
			return 
		stack, res = [(0, root)], []
		while stack:
			flag, node = stack.pop()
			if not node:
				continue
			if flag == 1:
				res.append(node.val)
			else:
				stack.append((1, node))
				stack.append((0, node.right))
				stack.append((0, node.left))
		return res
class Solution:
    def postorderTraversal(self, root: TreeNode) -> List[int]:
        stack, res = [], []
        while stack or root:
            while root:            # 下行循环,直到找到第一个叶子节点
                stack.append(root)
                if root.left:          # 能左就左,不能左就右
                    root = root.left 
                else:
                    root = root.right     
            s = stack.pop()
            res.append(s.val)
            #如果当前节点是上一节点的左子节点,则遍历右子节点
            if stack and s == stack[-1].left: 
                root = stack[-1].right
            else:
                root = None
        return res

4.二叉树的层序遍历

二叉树的层次遍历的迭代方法与前面不同,因为前面的都采用了深度优先搜索的方式,而层次遍历使用了广度优先搜索,广度优先搜索主要使用队列实现,也就不能使用前面的模板解法了。

广度优先搜索的步骤为:
1.初始化队列q,并将根节点root加入到队列中;
2.当队列不为空时:队列中弹出节点node,加入到结果中;如果左子树非空,左子树加入队列;如果右子树非空,右子树加入队列。

由于题目要求每一层保存在一个子数组中,所以我们额外加入了 level 保存每层的遍历结果,并使用for循环来实现。

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []
        q, res = [root], []
        while q:
            n = len(q)
            level = []
            for i in range(n):
                node = q.pop(0)
                level.append(node.val)
                if node.left:
                    q.append(node.left)
                if node.right:
                    q.append(node.right)
            res.append(level)
        return res
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值