什么是广度优先搜索算法

遍历意味着访问图的所有节点。广度优先遍历或广度优先搜索是一种递归算法,用于搜索图或树数据结构的所有顶点。标准的 BFS 实现将图的每个顶点放入以下两类之一:

  1. 访问过的顶点
  2. 未访问的顶点

该算法的目的是将每个顶点标记为已访问,同时避免循环。该算法的工作原理如下:

  1. 首先将图的任何一个顶点放在队列的后面。
  2. 取队列的最前面的项目并将其添加到访问列表中。
  3. 创建该顶点的相邻节点的列表。将不在访问列表中的添加到队列的后面。
  4. 继续重复步骤 2 和 3,直到队列为空。

该图可能有两个不同的不连接部分,因此为了确保我们覆盖每个顶点,我们还可以在每个节点上运行 BFS 算法

广度优先算法算法与队列

让我们通过一个例子来看看广度优先搜索算法是如何工作的。我们使用具有 5 个顶点的无向图。

广度优先 - 图1
具有 5 个顶点的无向图

我们从顶点 0 开始,BFS 算法首先将其放入访问列表并将其所有相邻顶点放入堆栈中。

广度优先 - 图2
访问起始顶点并将其相邻顶点加入队列

接下来,我们访问队列前面的元素,即 1 并转到其相邻节点。由于 0 已经被访问过,我们改为访问 2。

广度优先 - 图3
访问起始节点0的第一个邻居,即1

顶点 2 在 4 中有一个未访问的相邻顶点,因此我们将其添加到队列的后面并访问位于队列前面的 3。

广度优先 - 图4
访问 2 之前添加到队列以添加其邻居
广度优先 - 图5
4 仍在队列中

由于 3 的唯一相邻节点(即 0)已被访问,因此队列中仅剩下 4 个。

广度优先 - 图6
访问堆栈中的最后一个剩余项目以检查它是否有未访问的邻居

由于队列为空,我们就完成了图的广度优先遍历。

广度优先搜索算法复杂度

  • BFS算法的时间复杂度以O(V+E)的形式表示,其中V是节点数,E是边数。
  • 该算法的空间复杂度为 O(V)。

广度优先搜索算法的应用

  • 通过搜索索引建立索引
  • 用于 GPS 导航
  • 寻路算法
  • 在 Ford-Fulkerson 算法中寻找网络中的最大流量
  • 无向图中的循环检测
  • 在最小生成树中

广度优先搜索算法的伪码

  1. create a queue Q
  2. mark v as visited and put v into Q
  3. while Q is non-empty
  4. remove the head u of Q
  5. mark and enqueue all (unvisited) neighbours of u

广度优先搜索算法的实现

// BFS algorithm in Java

import java.util.*;

public class Graph {
  private int V;
  private LinkedList<Integer> adj[];

  // Create a graph
  Graph(int v) {
    V = v;
    adj = new LinkedList[v];
    for (int i = 0; i < v; ++i)
      adj[i] = new LinkedList();
  }

  // Add edges to the graph
  void addEdge(int v, int w) {
    adj[v].add(w);
  }

  // BFS algorithm
  void BFS(int s) {

    boolean visited[] = new boolean[V];

    LinkedList<Integer> queue = new LinkedList();

    visited[s] = true;
    queue.add(s);

    while (queue.size() != 0) {
      s = queue.poll();
      System.out.print(s + " ");

      Iterator<Integer> i = adj[s].listIterator();
      while (i.hasNext()) {
        int n = i.next();
        if (!visited[n]) {
          visited[n] = true;
          queue.add(n);
        }
      }
    }
  }

  public static void main(String args[]) {
    Graph g = new Graph(4);

    g.addEdge(0, 1);
    g.addEdge(0, 2);
    g.addEdge(1, 2);
    g.addEdge(2, 0);
    g.addEdge(2, 3);
    g.addEdge(3, 3);

    System.out.println("Following is Breadth First Traversal " + "(starting from vertex 2)");

    g.BFS(2);
  }
}