摘自计蒜客:http://www.jisuanke.com/course/35/7320
广度优先搜索算法(Breadth-First-Search, 简称BFS)是一种连通图的常用遍历策略,通常用于求起点到各点的最短路径,以及
求两点之间的最优路径等问题。首先来看看广度优先搜索的具体方法吧:
对于一个连通图,假设一开始所有顶点均未被访问,广度优先搜索的主要操作如下:
1.选择图中任意一个顶点v作为起点进行访问,并将顶点v标为已访问。
2.遍历并访问与顶点v相邻且未被访问的所有顶点c1,c2,...,ck;接着遍历并访问与顶点c1,c2,...,ck相邻且未被访问的顶点---也就是
依次访问所有相邻顶点的相邻顶点;依次类推,直到所有顶点均被访问。
从遍历过程中,可以看出,广度优先搜索,总是从某一起点出发,逐层进行搜索。每一层的顶点到起点的边数都是一样的。利用
这一思想,正好解释了为什么广度优先搜索可以求出图中一点到各点的最短距离,以及求某两点之间的最优路径等问题。
下面用一个小例子模拟广度优先搜索的遍历过程:
同样我们可以从遍历过程中发现,对一个连通图进行广度优先搜索,其实是在对该图的一个生成树进行搜索,这里的生成树我们称之为广度优先搜索树。如下图:
对于算法的具体实现,结合队列先进先出的特性,我们可以借助队列这一数据结构来实现广度优先搜索:
1.任意选择一个顶点v作为起点,加入队列;
2.访问队首元素v并标记,将其从队列中删除;
3.遍历与顶点v相邻且未被访问的所有顶点c1,c2,...,ck并依次加入到队列中;
4.重复第二步和第三步操作,直到队列为空。
代码实现如下:
#include <iostream>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
class Graph {
private:
int n;
bool *visited;
vector<int> *edges;
public:
Graph(int input_n) {
n = input_n;
edges = new vector<int>[n];
visited = new bool[n];
memset(visited, 0, n);
}
~Graph() {
delete[] edges;
delete[] visited;
}
void insert(int x, int y) {
edges[x].push_back(y);
edges[y].push_back(x);
}
void bfs(int start_vertex) {
queue<int> bfs_queue;
//首先将起点插入队列中并标记为已访问,然后不断弹出队首元素,并将和队首元素
//相邻的未访问顶点插入队列中同时设置为已访问。如此循环往复,便完成了广度优先搜索的过程;
bfs_queue.push(start_vertex);
visited[start_vertex] = true;
while (!bfs_queue.empty()) {
int vertex = bfs_queue.front();
cout << vertex << endl;
bfs_queue.pop();
for (int adj_vertex:edges[vertex]) {
if (!visited[adj_vertex]) {
visited[adj_vertex] = true;
bfs_queue.push(adj_vertex);
}
}
}
}
};
int main() {
int n, m, k;
cin >> n >> m;
Graph g(n);
for (int i = 0; i < m; ++i) {
int x, y;
cin >> x >> y;
g.insert(x, y);
}
cin >> k;
g.bfs(k);
return 0;
}