图的遍历(广度优先算法)

523 阅读2分钟

这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

广度优先遍历算法(BFS) 先看图:

image.png

广度优先算法的步骤时这样的:从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)