深度优先搜索(DFS)和广度优先搜索(BFS)
深度优先搜索(DFS) 和 广度优先搜索(BFS) 是两种常见的图(或树)遍历算法,它们用于探索图或树中的所有节点。两者的区别主要在于遍历的顺序和使用的数据结构。
1. 深度优先搜索(DFS)
定义:
- 深度优先搜索(DFS)是一种沿着树的深度遍历图的算法。它尽可能深入每一条分支,当节点的所有子节点都被访问过后,再回溯到父节点继续搜索。
- DFS 使用递归或栈来实现,通常会先访问当前节点的子节点,直到到达叶子节点或没有未访问的节点为止。
实现思路:
- 从起始节点开始,访问当前节点并标记为已访问。
- 递归地访问当前节点的邻接节点(或子节点)。
- 如果没有更多未访问的邻接节点,回溯到上一个节点,继续检查其未访问的邻接节点。
- 如果所有节点都被访问过,算法结束。
数据结构:使用栈(Stack)或者递归来实现。
时间复杂度:
- 时间复杂度:O(V + E),其中 V 是图中的节点数,E 是边的数目。每个节点和每条边都需要访问一次。
- 空间复杂度:O(V),栈空间或递归调用栈的深度可能会达到图的节点数。
特点:
- DFS 适合搜索路径、拓扑排序、连通分量等问题。
- 它可能会进入无限循环,特别是在图中存在环时,因此需要避免重复访问。
代码示例(Python):
# 深度优先搜索 DFS
def dfs(graph, start, visited=None):
if visited is None:
visited = set()
visited.add(start)
print(start, end=' ')
for neighbor in graph[start]:
if neighbor not in visited:
dfs(graph, neighbor, visited)
# 示例图(邻接表表示法)
graph = {
'A': ['B', 'C'],
'B': ['A', 'D', 'E'],
'C': ['A', 'F'],
'D': ['B'],
'E': ['B', 'F'],
'F': ['C', 'E']
}
dfs(graph, 'A') # 从节点 A 开始深度优先搜索
输出:
A B D E F C
2. 广度优先搜索(BFS)
定义:
- 广度优先搜索(BFS)是一种从根节点开始,首先访问节点的所有邻接节点,然后逐层向外扩展,访问每一层的节点。
- BFS 使用队列来存储待访问的节点,每次从队列中取出一个节点进行访问,然后将该节点的所有未访问的邻接节点加入队列。
实现思路:
- 从起始节点开始,将其加入队列并标记为已访问。
- 从队列中取出一个节点,访问该节点并将其所有未访问的邻接节点加入队列。
- 重复步骤2,直到队列为空,即所有可访问节点都被遍历过。
数据结构:使用队列(Queue)来实现。
时间复杂度:
- 时间复杂度:O(V + E),每个节点和每条边都需要访问一次。
- 空间复杂度:O(V),队列可能会存储图中所有的节点。
特点:
- BFS 适用于寻找最短路径(无权图),层级遍历,或者是检查连通性等问题。
- BFS 会遍历每一层的节点,适用于处理最短路径和最短距离等问题。
代码示例(Python):
# 广度优先搜索 BFS
from collections import deque
def bfs(graph, start):
visited = set()
queue = deque([start]) # 初始化队列,加入起始节点
visited.add(start)
while queue:
node = queue.popleft() # 弹出队列的第一个节点
print(node, end=' ')
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor) # 将未访问的邻居节点加入队列
# 示例图(邻接表表示法)
graph = {
'A': ['B', 'C'],
'B': ['A', 'D', 'E'],
'C': ['A', 'F'],
'D': ['B'],
'E': ['B', 'F'],
'F': ['C', 'E']
}
bfs(graph, 'A') # 从节点 A 开始广度优先搜索
输出:
A B C D E F
DFS 和 BFS 的区别
| 特点 | 深度优先搜索(DFS) | 广度优先搜索(BFS) |
|---|---|---|
| 遍历方式 | 先深入子节点,直到无法继续,再回溯 | 按层次逐层遍历,先访问同一层的节点 |
| 使用的数据结构 | 栈(或递归调用栈) | 队列 |
| 适用场景 | 适用于需要探索路径、拓扑排序等场景 | 适用于求解最短路径、层次遍历等场景 |
| 时间复杂度 | O(V + E) | O(V + E) |
| 空间复杂度 | O(V) | O(V) |
| 是否能找到最短路径 | 无法保证 | 能找到最短路径 |
| 搜索顺序 | 深度优先,可能先探索一条路径直到终点 | 广度优先,先访问近距离节点 |
总结:
- DFS 适合用来查找图中的路径、拓扑排序、检测环、连通性等问题。
- BFS 适合用来查找最短路径、层次遍历,或处理无权图的最短距离问题。
根据问题的不同,选择适合的搜索算法会使问题的求解更加高效。