好的!下面是关于【算法】BFS(广度优先搜索)在最短路径问题和拓扑排序中的详细讲解:
【算法】BFS(广度优先搜索)—— 最短路径问题与拓扑排序解析
目录
- BFS基础概念
- BFS求解最短路径问题
- BFS实现示例(无权图最短路径)
- BFS在拓扑排序中的应用
- 拓扑排序实现(Kahn算法)
- BFS相关经典题目推荐
- 注意事项与复杂度分析
- 拓展内容
1️⃣ BFS基础概念
- 定义:广度优先搜索是一种层级遍历图或树的算法,从源节点开始,逐层访问其邻居节点,直到所有可达节点被访问。
- 数据结构:通常使用队列实现先进先出(FIFO)。
- 特点:在无权图中,BFS可以找到从起点到其他节点的最短路径(边数最少)。
2️⃣ BFS求解最短路径问题
- 适用范围:无权图(或权重相同的图),比如迷宫、社交网络中的最短跳数。
- 思路:
- 从起点开始,将其入队。
- 依次访问队头节点的所有未访问邻居,加入队列。
- 记录每个节点的距离或路径信息。
- 直到找到目标节点或遍历结束。
3️⃣ BFS示例代码:无权图最短路径
from collections import deque
def bfs_shortest_path(graph, start, target):
visited = set()
queue = deque([(start, 0)]) # (节点,距离)
visited.add(start)
while queue:
node, dist = queue.popleft()
if node == target:
return dist
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append((neighbor, dist + 1))
return -1 # 不可达
4️⃣ BFS在拓扑排序中的应用
- 拓扑排序:对有向无环图(DAG)节点的线性排序,使得所有有向边
(u -> v)
中,u
在v
之前。 - 使用BFS实现拓扑排序的思路(Kahn算法):
- 统计每个节点的入度(指向该节点的边数)。
- 将所有入度为0的节点入队。
- 队列中弹出节点,加入结果序列,同时将其所有邻居的入度减一。
- 如果邻居入度变为0,加入队列。
- 直到队列空,检查是否所有节点都被访问,若未访问节点存在,则说明图中有环。
5️⃣ 拓扑排序实现(Kahn算法)
from collections import deque, defaultdict
def topo_sort(num_nodes, edges):
in_degree = [0] * num_nodes
graph = defaultdict(list)
for u, v in edges:
graph[u].append(v)
in_degree[v] += 1
queue = deque([i for i in range(num_nodes) if in_degree[i] == 0])
topo_order = []
while queue:
node = queue.popleft()
topo_order.append(node)
for neighbor in graph[node]:
in_degree[neighbor] -= 1
if in_degree[neighbor] == 0:
queue.append(neighbor)
if len(topo_order) == num_nodes:
return topo_order
else:
return [] # 有环,无拓扑排序
6️⃣ BFS相关经典题目推荐
题目编号 | 题目名称 | 重点讲解 |
---|---|---|
107 | 二叉树的层序遍历 | BFS层级遍历树结构 |
127 | 单词接龙 | BFS最短路径应用 |
210 | 课程表 II | BFS拓扑排序 |
1091 | 二进制矩阵中的最短路径 | BFS最短路径 |
205 | 同构字符串 | 拓扑排序验证 |
7️⃣ 注意事项与复杂度分析
- 时间复杂度:O(V + E),遍历所有节点和边。
- 空间复杂度:O(V),用于队列和访问记录。
- 注意点:
- 对于拓扑排序,必须检测环存在。
- BFS适合无权图或权重相同的图;加权图用Dijkstra等算法。
- 确保图结构完整且节点编号合理。
8️⃣ 拓展内容
- 多源BFS:多个起点同时入队,用于求最短距离集合。
- 双向BFS:从起点和终点同时搜索,提升效率。
- BFS与DFS对比:BFS层次遍历,DFS深入遍历,适合不同场景。
发表回复