宽度优先搜索(BFS)

568 阅读2分钟

宽度优先搜索

宽度优先搜索(BFS)是一种图形搜索算法,它从一个源节点开始,遍历图中所有节点,按照距离源节点逐层向外扩展,直到遍历完所有连通节点。在扩展每一层节点时,BFS算法保证所有节点都被访问且最小化了访问的节点数量。BFS算法常用于解决最短路径问题和状态转换问题。BFS算法可以用队列来实现,因为它需要按照先进先出的顺序处理节点。在实现BFS时,需要记录每个节点是否已经访问过,以避免死循环的出现。

步骤

  1. 将起点放入队列中。
  2. 当队列不为空时,执行以下步骤:
  3. 取出队首元素。
  4. 遍历该元素的所有邻居节点,如果邻居节点未被访问过,就将其标记为已访问,并将其放入队列中。
  5. 标记当前节点为已访问。
  6. 如果目标节点被标记为已访问,搜索结束,返回结果;否则搜索失败。

在执行过程中,宽度优先搜索使用一个队列来存储待访问的节点。每次取出队首元素,遍历其邻居节点并放入队列,直到队列为空或找到目标节点为止。宽度优先搜索保证了在所有路径长度相同的情况下,它能够找到最短路径。

需要注意的是,在执行过程中,为了避免重复访问同一个节点,需要对每个节点进行标记,表示其是否已经被访问过。同时,如果搜索的是无向图,需要在遍历邻居节点时,排除已经访问过的节点。

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循环,直到队列为空为止,每次从队列中取出第一个节点,并将其添加到遍历结果列表中。接着,遍历该节点的相邻节点,并将未访问的相邻节点添加到队列中,等待访问。