宽度优先搜索
宽度优先搜索(BFS)是一种图形搜索算法,它从一个源节点开始,遍历图中所有节点,按照距离源节点逐层向外扩展,直到遍历完所有连通节点。在扩展每一层节点时,BFS算法保证所有节点都被访问且最小化了访问的节点数量。BFS算法常用于解决最短路径问题和状态转换问题。BFS算法可以用队列来实现,因为它需要按照先进先出的顺序处理节点。在实现BFS时,需要记录每个节点是否已经访问过,以避免死循环的出现。
步骤
- 将起点放入队列中。
- 当队列不为空时,执行以下步骤:
- 取出队首元素。
- 遍历该元素的所有邻居节点,如果邻居节点未被访问过,就将其标记为已访问,并将其放入队列中。
- 标记当前节点为已访问。
- 如果目标节点被标记为已访问,搜索结束,返回结果;否则搜索失败。
在执行过程中,宽度优先搜索使用一个队列来存储待访问的节点。每次取出队首元素,遍历其邻居节点并放入队列,直到队列为空或找到目标节点为止。宽度优先搜索保证了在所有路径长度相同的情况下,它能够找到最短路径。
需要注意的是,在执行过程中,为了避免重复访问同一个节点,需要对每个节点进行标记,表示其是否已经被访问过。同时,如果搜索的是无向图,需要在遍历邻居节点时,排除已经访问过的节点。
Java语言实现宽度优先搜索
import java.util.*;
public class BFS {
// 定义图的邻接表形式
private Map<Integer, List<Integer>> graph;
// 构造函数,初始化图
public BFS(int[][] edges) {
graph = new HashMap<>();
// 遍历边列表,将每个节点和其相邻节点添加到图的邻接表中
for (int[] edge : edges) {
int from = edge[0], to = edge[1];
graph.putIfAbsent(from, new ArrayList<>());
graph.putIfAbsent(to, new ArrayList<>());
graph.get(from).add(to);
graph.get(to).add(from);
}
}
// 宽度优先搜索方法
public List<Integer> bfs(int start) {
List<Integer> result = new ArrayList<>(); // 保存遍历结果的列表
Queue<Integer> queue = new LinkedList<>(); // 队列,用于辅助遍历
queue.offer(start); // 将起始节点添加到队列中
Set<Integer> visited = new HashSet<>(); // 已访问的节点集合
while (!queue.isEmpty()) {
int node = queue.poll(); // 取出队列中的第一个节点
if (!visited.contains(node)) { // 如果该节点未被访问过
visited.add(node); // 将该节点标记为已访问
result.add(node); // 将该节点添加到遍历结果列表中
// 将该节点的相邻节点添加到队列中,等待访问
for (int neighbor : graph.getOrDefault(node, new ArrayList<>())) {
if (!visited.contains(neighbor)) {
queue.offer(neighbor);
}
}
}
}
return result;
}
// 测试
public static void main(String[] args) {
int[][] edges = {{0, 1}, {0, 2}, {1, 3}, {1, 4}, {2, 5}, {2, 6}};
BFS bfs = new BFS(edges);
List<Integer> result = bfs.bfs(0);
System.out.println(result);
}
}
这个BFS实现使用邻接表表示图,以方便遍历节点。在构造函数中,遍历边列表,将每个节点和其相邻节点添加到图的邻接表中。
在BFS方法中,我们使用一个队列来辅助遍历。首先将起始节点添加到队列中,并使用一个集合来保存已访问的节点。然后,使用一个while循环,直到队列为空为止,每次从队列中取出第一个节点,并将其添加到遍历结果列表中。接着,遍历该节点的相邻节点,并将未访问的相邻节点添加到队列中,等待访问。