简介:
广度优先搜索算法(又称宽度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。
算法思想:
首先访问起始顶点S,在一次访问S所有尚未访问到的邻居;再按后者被访问的先后次序,逐个访问他们的邻居…;直至搜索完所有能到达的顶点。类似树结构中的层次遍历。
算法步骤:
- 首先从起始顶点出发,访问起始顶点
- 依次访问起始顶点未曾访问的邻接顶点
- 分别从这些邻接点出发依次访问他们的邻接点,并且保证先被访问的顶点的邻接点先于后被访问的顶点的邻接点
- 重复3,直至无邻接点可访问为止
根据上述特性,我们可以采用队列暂存每个顶点。
- 起始顶点先入队
- 弹出队头元素,查看其是否有未被访问过的邻接点,若有则入队
- 重复上述过程,直至队列为空
为了记录定点是否被访问过,我们可以使用一个标记数组,查看元素是否被访问过。
代码示例:
邻接矩阵:
#include<iostream>
#include<queue>
using namespace std;
const int N = 100;
int graph[N][N];//邻接矩阵存储图
bool visted[N];//标记数组
int seq[N];//记录搜索顺序
void init_graph(){//初始化邻接矩阵
for(int i = 0; i < N; i++){//初始化邻接矩阵
for(int j = 0; j < N; j++)
graph[i][j] = 0;
}
}
void bfs(int s, int n){
queue<int> q;
q.push(s);
visted[s] = true;
int count = 0;
while(q.size() > 0){
int t = q.front();
for(int i = 1; i <= n; i++){
if(graph[t][i] != 0){
if(!visted[i]){
visted[i] = true;
q.push(i);
}
}
}
seq[count++] = t;
q.pop();
}
}
int main(){
int n, m, s;
cin >> n >> m >> s;
init_graph();
for(int i = 0; i < m; i++){//输入顶点与边
int x, y;
cin >> x >> y;
graph[x][y] = 1;
}
bfs(s, n);
for(int i = 0; i < n; i++)
cout << seq[i] << " ";
return 0;
}
观察上述代码,不难发现,基本语句最坏情况下要执行n^ 2次,因此时间复杂度为O(n^2)。
邻接表:
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define MAX_SIZE 100
bool visted[MAX_SIZE];
typedef struct Enode{
int index;
Enode *next;
}*Edge;
struct Vnode{
int data;
Enode *next;
};
void init_v_node(Vnode *apex, int n){
for(int i = 0; i <= n; i++){
apex[i].data = 0;
apex[i].next = NULL;
}
}
void create_list(Vnode *apex, int m, int n){
for(int i = 0; i < m; i++){//更新图的连通情况
int x, y;
cin >> x >> y;
apex[x].data = x;
Edge t = new Enode;
t->index = y;
t->next = apex[x].next;
apex[x].next = t;
}
}
void bfs(Vnode *apex, int s){
queue<int> q;
q.push(s);
visted[s] = true;
cout << s << " ";
while(q.size() > 0){
Edge p = apex[q.front()].next;
while(p != NULL){
if(!visted[p->index]){
cout << p->index << " ";
visted[p->index] = true;
q.push(p->index);
}
p = p->next;
}
q.pop();
}
}
int main(){
int n, m;
cin >> n >> m;
Vnode apex[n+1];//顺序表存储顶点
init_v_node(apex, n);
create_list(apex, m, n);
bfs(apex, 1);
return 0;
}