广度优先搜索(Breadth-First Search, BFS)是一种用于遍历或搜索树形结构(如树、图等)的算法。它按照层次顺序从根节点开始,依次访问离根节点最近的节点,直至遍历到整个树或图。BFS特别适用于寻找两点间最短路径(当所有边的权重相同)、判断图的连通性、生成树的层次遍历序列等任务。以下是BFS的主要特点和步骤:
主要特点:
-
队列实现:BFS通常借助队列(先进先出,FIFO)数据结构来实现。新发现的节点总是被添加到队列尾部,而要访问的下一个节点总是从队列头部取出。
-
最短路径性质:在无权图中,BFS从源节点出发找到的任一目标节点的路径是所有从源节点到该目标节点的路径中最短的(即经过的边数最少)。这一特性使得BFS成为解决最短路径问题的有效工具,特别是当边的权重相等时。
-
层次遍历:在树形结构中,BFS按层次顺序遍历节点,先访问同一层次的所有节点,再向下一层推进。这种遍历方式生成的节点序列反映了节点间的相对位置关系。
-
连通性判断:BFS同样可以用于判断图的连通性。从一个起点出发,如果BFS能够访问到所有节点,则该图是连通的。
-
空间效率:相对于深度优先搜索(DFS),BFS可能需要更大的内存空间,因为它通常需要存储整层节点以确保按照正确的顺序访问。
基本步骤:
-
初始化:
- 创建一个队列,将起始节点放入队列中。
- 使用一个数据结构(如集合或数组)记录已访问节点,避免重复访问。
-
循环处理:
- 当队列非空时,从队列头部取出一个节点(当前节点)。
- 对当前节点的每个未访问邻居节点:
- 将邻居节点加入队列尾部。
- 标记邻居节点为已访问。
-
结束条件:当队列为空且没有新的节点加入时,说明所有与起始节点连通的节点都已被访问,BFS结束。
应用实例:
BFS在许多问题中都有应用,包括但不限于:
- 寻找图中两个节点间的最短路径(在所有边权重相等的情况下)。
- 检查图是否连通。
- 拓扑排序(针对有向无环图,即DAG)。
- 社交网络中的好友推荐。
- 检索关键词在网络中的传播模型。
- 网络爬虫的网页抓取策略。
以下是BFS的Python实现示例(以无向图为例,使用邻接表表示):
Python
1from collections import deque
2
3def bfs(graph, start):
4 visited = set()
5 queue = deque([start])
6
7 while queue:
8 node = queue.popleft()
9 visited.add(node)
10
11 for neighbor in graph[node]:
12 if neighbor not in visited:
13 queue.append(neighbor)
14
15 return visited
16
17# 示例
18graph = {
19 'A': ['B', 'C'],
20 'B': ['A', 'D', 'E'],
21 'C': ['A', 'F'],
22 'D': ['B'],
23 'E': ['B', 'F'],
24 'F': ['C', 'E']
25}
26
27visited_nodes = bfs(graph, 'A')
28print("Visited nodes:", visited_nodes)
这段代码实现了BFS的基本逻辑,通过使用双端队列(deque)存储待访问节点,并使用集合visited
记录已访问节点,避免重复访问。遍历结束后,返回所有已访问节点的集合。