广度优先搜索
广度优先搜索(BFS)是一种图遍历算法,按层遍历节点。
概述
广度优先搜索从起始节点开始,依次访问所有相邻节点,然后再访问下一层节点。
算法步骤
- 访问起始节点
- 依次访问所有相邻节点
- 对每个相邻节点重复步骤 2
实现
python
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)
return visited
# 示例图
graph = {
'A': ['B', 'C'],
'B': ['A', 'D', 'E'],
'C': ['A', 'F'],
'D': ['B'],
'E': ['B', 'F'],
'F': ['C', 'E']
}
print("BFS 遍历结果:")
bfs(graph, 'A') # A B C D E F复杂度分析
| 复杂度 | 值 |
|---|---|
| 时间复杂度 | O(V + E) |
| 空间复杂度 | O(V) |
应用场景
最短路径
python
def bfs_shortest_path(graph, start, end):
visited = {start}
queue = deque([(start, [start])])
while queue:
node, path = queue.popleft()
if node == end:
return path
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append((neighbor, path + [neighbor]))
return None # 无路径
# 示例
path = bfs_shortest_path(graph, 'A', 'F')
print(f"\n最短路径: {path}") # 最短路径: ['A', 'C', 'F']层序遍历
python
def level_order_traversal(root):
if root is None:
return []
result = []
queue = deque([root])
while queue:
level_size = len(queue)
current_level = []
for _ in range(level_size):
node = queue.popleft()
current_level.append(node.value)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(current_level)
return result
# 示例二叉树
class TreeNode:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
print("\n层序遍历结果:", level_order_traversal(root)) # [[1], [2, 3], [4, 5]]无权图最短路径
python
def bfs_distance(graph, start):
distance = {node: -1 for node in graph}
distance[start] = 0
queue = deque([start])
while queue:
node = queue.popleft()
for neighbor in graph[node]:
if distance[neighbor] == -1:
distance[neighbor] = distance[node] + 1
queue.append(neighbor)
return distance
# 示例
distances = bfs_distance(graph, 'A')
print("\n各节点距离:", distances) # {'A': 0, 'B': 1, 'C': 1, 'D': 2, 'E': 2, 'F': 2}变体
双向 BFS
python
def bidirectional_bfs(graph, start, end):
if start == end:
return [start]
forward_visited = {start}
backward_visited = {end}
forward_queue = deque([(start, [start])])
backward_queue = deque([(end, [end])])
while forward_queue and backward_queue:
# 前向搜索
node, path = forward_queue.popleft()
for neighbor in graph[node]:
if neighbor in backward_visited:
# 找到相遇点
return path + find_path(backward_queue, neighbor)[::-1]
if neighbor not in forward_visited:
forward_visited.add(neighbor)
forward_queue.append((neighbor, path + [neighbor]))
# 后向搜索
node, path = backward_queue.popleft()
for neighbor in graph[node]:
if neighbor in forward_visited:
# 找到相遇点
return find_path(forward_queue, neighbor) + path[::-1]
if neighbor not in backward_visited:
backward_visited.add(neighbor)
backward_queue.append((neighbor, path + [neighbor]))
return None
def find_path(queue, target):
for node, path in queue:
if node == target:
return path
return []与 DFS 的对比
| 特性 | BFS | DFS |
|---|---|---|
| 数据结构 | 队列 | 栈 |
| 空间复杂度 | O(V) | O(V) |
| 最短路径 | 保证 | 不保证 |
| 适用场景 | 最短路径、层序遍历 | 连通性检测、拓扑排序 |
注意事项
- 队列顺序: 使用队列保证按层遍历
- 访问标记: 必须标记已访问的节点,避免重复访问
- 内存使用: 在最坏情况下,可能需要存储所有节点