思维导图:
广度优先遍历的原理:
类似与树的层次遍历
1、先入队一个节点
2、然后入队与该节点相邻的且未被访问过的节点,然后出队该节点
3、重复2过程直到所有的节点均被访问
ps:
实现方法是用一个标记数组加队列完成的,标记数组的作用是标记节点是否被访问过
PS:
当采用邻接数组存储时,由于邻接矩阵唯一,所以广度优先遍历序列也唯一。
当采用邻接表存储时,由于边表序列不唯一,所以广度优先遍历序列也不唯一。
广度优先遍历的代码实现:
//visited是访问标记数组
//处理非连通图的情况
bool BFSTraverse(Graph G){
for(int i=0;i<G.vexnum;++i)
visited[i] = false;
InitQueue(Q);
for(int i=0;i<G.vexnum;++i){
if(!visited[i])
BFS(G,i);
}
}
void BFS(Graph G,int v){
visit(v); //访问v顶点
visited[v] = True; //修改该顶点对应数组的值为true
EnQueue(Q,v); //入队
while(!isEmpty(Q)){ //不空还有未遍历到的节点
DeQueue(Q,v); //出队v
for(w = FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w)) //找到所有符合条件的邻接节点
if(!visited[w]){ //w是否被访问
visit[w]; //访问
visited[w] = true; //修改该顶点对应数组的值为true
EnQueue(Q,w); //入队
}
}
}
bool BFSTraverse(Graph G,int v){
for(int i=0;i<G.vexnum;++i)
visited[i] = false;
InitQueue(Q);
for(int i=0;i<G.vexnum;++i){
if(!visited[i])
visit(v); //访问v顶点
visited[v] = True; //修改该顶点对应数组的值为true
EnQueue(Q,v); //入队
while(!isEmpty(Q)){ //不空还有未遍历到的节点
DeQueue(Q,v); //出队v
for(w = FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w)) //找到所有符合条件的邻接节点
if(!visited[w]){ //w是否被访问
visit[w]; //访问
visited[w] = true; //修改该顶点对应数组的值为true
EnQueue(Q,w); //入队
}
}
}
}
广度优先遍历的性能分析:
无权图单源最短路径问题:
ps:
无权图:无权值或权值相等
单源:从一个顶点出发
最短路径:广度优先遍历
void BFS_Distance(Graph G,int v){
for(int i=0;i<G.vexnum;++i)
d[i] = MAX;
visited[v] = true;
d[v] = 0;
EnQueue(Q,v);
while(!isEmpty(Q)){ //不空还有未遍历到的节点
DeQueue(Q,v); //出队v
for(w = FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w)) //找到所有符合条件的邻接节点
if(!visited[w]){ //w是否被访问
visited[w] = true; //修改该顶点对应数组的值为true
d[w] = d[v] + 1;
EnQueue(Q,w); //入队
}
}
}
广度优先生成树:
ps: 节点5是由节点2访问的,而不是节点4访问的,所有没有4到5的边