这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战
广度优先遍历算法(BFS) 先看图:
广度优先算法的步骤时这样的:从a出发,a访问后,接着访问a的没有访问过的领接点 b,c,接着访问b的未访问过的领接点d,c,再访问c的未访问的领接点f,g,这样最后到h 最后的顺序则未abcdefgh 这其实就时二叉树的层次遍历。
在上面的这个基础上我们在来思考,广度优先遍历时按层次进行查找,他每走一个结点就要检查和他相邻的结点? 比如b,c访问后,我们怎么知道从b,c的领接结点开始访问呢(即d e f g)?因为队列有先进先出的特点 这时我们就可以借助一个队列来实现。接下来一起看代码 图的数据结构参照上一篇文章
图的一些基本操作:
FirstNeighbor(G,x):求图G中顶点x的第一个邻接点,若有则返回第一个邻接点的索引下标,若x没有邻接点或图中不存在顶点x,则返回-1
NextNeighbor(G,x,y):假设图G中顶点y是顶点x的一个邻接点,返回除y外顶点x的下一个邻接点的索引下标,若y是x的最后一个邻接点,则返回-1
bool visited[MaxVertex]; //标记访问数组
void BFSTraverse(Grapha G){
for(i=0;i<G.vertexNum;i++){
visited[i] = false; //初始化访问数组
}
InitQueue(Q); //初始化辅助队列
for(i=0;i<G.vertexNum;i++){
if(!visited[i]){
BFS(G,i);
}
}
}
void BFS(Graph G,int v){
visit(v); //访问结点v
visited[v] = true; //对访问后的结点进行标记
Enqueue(Q,v); //将访问后的结点入队列
while(!isEmpty(Q)){ //循环队列 知道队列为空
Dequeue(Q,v); //出队列获取顶点v
for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w)){
//判断顶点v的领结点是否有被访问 没有访问则访问,且进队列,若无则不作任何操作(注意这个for循环的条件)
if(!visited[w]){
visit(w);
visited[w] = true;
Enqueue(Q,w);
}
}
}
}
性能分析: 时间复杂度:
采用领接矩阵存储:O(|V|2)
采用领接表存储:O(|V|+|E|)
空间复杂度:
O(|V|)(借助一个辅助队列Q)