在二叉树遍历问题中,有三种常见的遍历方式:前序遍历、中序遍历和后序遍历。以下是这三种遍历方式的递归模板:
1. 前序遍历(Preorder Traversal):
按照 根节点 -> 左孩子 -> 右孩子 的方式遍历
def preorderTraversal(root):
if not root:
return []
result = []
result.append(root.val) # 处理当前节点
result.extend(preorderTraversal(root.left)) # 递归处理左子树
result.extend(preorderTraversal(root.right)) # 递归处理右子树
return result
2. 中序遍历(Inorder Traversal):
按照 左孩子 -> 根节点 -> 右孩子 的方式遍历,即「中序序遍历」
def inorderTraversal(root):
if not root:
return []
result = []
result.extend(inorderTraversal(root.left)) # 递归处理左子树
result.append(root.val) # 处理当前节点
result.extend(inorderTraversal(root.right)) # 递归处理右子树
return result
3. 后序遍历(Postorder Traversal):
按照 左孩子 -> 右孩子 -> 根节点 的方式遍历,即「后序序遍历」
def postorderTraversal(root):
if not root:
return []
result = []
result.extend(postorderTraversal(root.left)) # 递归处理左子树
result.extend(postorderTraversal(root.right)) # 递归处理右子树
result.append(root.val) # 处理当前节点
return result
这些模板基于递归思想,对二叉树进行深度优先遍历。对于每个节点,都会首先处理当前节点,然后递归处理左子树和右子树。这样可以保证在遍历过程中按照前序、中序或后序的顺序访问节点。
dfs实现
例如 二叉树中序遍历
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]:
def dfs(root):
if not root:
return
#ans 作为 dfs 函数的参数传递 dfs(root, ans) 就不需不需要使用 nonlocal
dfs(root.left)
#ans 是在 dfs 函数之外定义的,但是在 dfs 函数内部被修改。
#在这种情况下,如果你直接在 dfs 函数内使用 ans,Python 会将其视为局部变量,
#并且在递归调用时,每一层递归都会有一个独立的局部变量 ans,而不会影响外部的 ans
nonlocal ans
ans.append(root.val) #这三行交换位置实现二叉树前中后序遍历
dfs(root.right)
ans = []
dfs(root)
return ans
在实际应用中,也可以使用迭代的方法,例如使用栈来模拟递归的过程,实现非递归的遍历。
迭代法模板
以下是使用迭代法进行二叉树遍历的模板。这里使用栈来模拟递归的过程,实现非递归的遍历。
1. 前序遍历(Preorder Traversal):
def preorderTraversal(root):
if not root:
return []
result = []
stack = [root]
while stack:
node = stack.pop()
result.append(node.val) # 处理当前节点
if node.right:
stack.append(node.right) # 先加入右子树,因为栈是先入后出
if node.left:
stack.append(node.left) # 再加入左子树
return result
2. 中序遍历(Inorder Traversal):
def inorderTraversal(root):
if not root:
return []
result = []
stack = []
while stack or root:
while root:
stack.append(root)
root = root.left # 先一直往左走到底,模拟递归的过程
node = stack.pop()
result.append(node.val) # 处理当前节点
root = node.right # 处理右子树,如果右子树为空,下一次循环会继续处理栈中的节点
return result
3. 后序遍历(Postorder Traversal):
def postorderTraversal(root):
if not root:
return []
result = []
stack = [root]
while stack:
node = stack.pop()
result.insert(0, node.val) # 插入到结果列表的开头,模拟逆序
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)
return result
这些迭代法的模板使用栈来辅助遍历,通过不断地迭代,模拟了递归的过程。这样可以在不使用递归的情况下实现二叉树的前序、中序和后序遍历。
其他优秀模板链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/642769/python3-die-dai-bian-li-chang-gui-jie-fa-1egc/
https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/247053/tu-jie-er-cha-shu-de-si-chong-bian-li-by-z1m/
二叉树层序遍历
基本使用BFS(用栈储存)
层次遍历就是按照每一层从左向右的方式进行遍历
解题思路:
I. 按层打印: 题目要求的二叉树的 从上至下 打印(即按层打印),又称为二叉树的 广度优先搜索(BFS)。BFS 通常借助 队列 的先入先出特性来实现。
II. 每层打印到一行: 将本层全部节点打印到一行,并将下一层全部节点加入队列,以此类推,即可分为多行打印。
算法流程:
特例处理: 当根节点为空,则返回空列表 [] 。
初始化: 打印结果列表 res = [] ,包含根节点的队列 queue = [root] 。
BFS 循环: 当队列 queue 为空时跳出。
新建一个临时列表 tmp ,用于存储当前层打印结果。
当前层打印循环: 循环次数为当前层节点数(即队列 queue 长度)。
出队: 队首元素出队,记为 node。
打印: 将 node.val 添加至 tmp 尾部。
添加子节点: 若 node 的左(右)子节点不为空,则将左(右)子节点加入队列 queue 。
将当前层结果 tmp 添加入 res 。
返回值: 返回打印结果列表 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 levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
if root is None:
return []
ans = [] #存放结果
q = deque() #使用双端队列
q.append(root)#将根节点压入队列
while q:
vals = [] #临时存放当前层节点值
for _ in range(len(q)): #遍历某一层节点
node = q.popleft()
vals.append(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
ans.append(vals) #将当前层的节点值压入ans
return ans