【Python】二叉树的广度优先搜索和深度优先搜索
程序员文章站
2022-05-22 20:56:49
...
文章目录
1. 什么是二叉树
二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。
2. 本文用到的二叉树例子
1
/ \
2 3
/ \ / \
4 5 6 7
3. 什么是广度优先搜索(BFS)
BFS(Breath First Search),概念可以自行百度,通俗的讲就是,依次遍历树每一层节点,按照上面给出的例子,预期得到的是:[1, 2, 3, 4, 5, 6, 7]
4. 什么是深度优先搜索(DFS)
DFS(Deep First Search),概念可以自行百度,通俗的讲就是,对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次,按照上面给出的例子,预期得到的是:[1, 2, 4, 5, 3, 6, 7]
5. 使用队列实现BFS
Python常用的有两个队列类,线程安全的FIFO队列(First in First out 先进先出)queue.Queue,多进程中使用的队列 multiprocessing.Queue。其实,Python中的列表也可以实现队列的先进先出的功能(进队列用append,出队列取第1个元素),只不过它不是线程安全的。为了方便理解,我们用列表来模拟队列实现BFS。
# 先定义一个二叉树的节点类
class TreeNode:
def __init__(self, x):
self.val = x # 该节点的值
self.left = None # 该节点的左子树
self.right = None # 该节点的右子树
# 构造例子中的二叉树
"""
1
/ \
2 3
/ \ / \
4 5 6 7
"""
root = TreeNode(1)
root.left = TreeNode(2)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
root.right = TreeNode(3)
root.right.left = TreeNode(6)
root.right.right = TreeNode(7)
# 广度优先搜索
def bfs(root):
res = []
q = [root] # 先把根节点放进队列中
while q: # 当队列不为空时进入循环体
current_node = q.pop(0) # 取出队列的第一个节点
res.append(current_node.val) # 把该节点的值加入结果集
if current_node.left: # 如果左子树不为空,就加入队列
q.append(current_node.left)
if current_node.right: # 如果右子树不为空,就加入队列
q.append(current_node.right)
return res
print(bfs(root))
# 输出:[1, 2, 3, 4, 5, 6, 7]
6. 使用栈实现DFS
同样的,列表也可以模拟栈先进后出的功能(入栈使用append,出栈取最后一个元素)。我们先把根节点压入栈中,然后判断栈是否为空,不为空则进入循环体,取出栈顶节点,然后依次把栈顶节点的右子树和左子树压入栈中,因为栈先进后出的原则,这样取出来的顺序就是 左 - 右 - 根。
# 二叉树直接复用上面的例子,不再重复构建
# 深度优先搜索
def dfs(root):
res = []
q = [root] # 先把根节点放进栈中
while q: # 当栈不为空时进入循环体
current_node = q.pop() # 取出栈顶节点
res.append(current_node.val) # 把该节点的值加入结果集
if current_node.right: # 如果右子树不为空,就压入栈
q.append(current_node.right)
if current_node.left: # 如果左子树不为空,就压入栈
q.append(current_node.left)
return res
print(dfs(root))
# 输出:[1, 2, 4, 5, 3, 6, 7]
7. 使用递归实现DFS
# 二叉树直接复用上面的例子,不再重复构建
res = []
# 使用递归实现深度优先搜索
def dfs_recur(node):
if not node: # 递归结束的条件是当该节点为None时
return
res.append(node.val) # 把该节点的值加入结果集
dfs_recur(node.left) # 对左子树进行递归
dfs_recur(node.right) # 对右子树进行递归
dfs_recur(root)
print(res)
# 输出:[1, 2, 4, 5, 3, 6, 7]