连通图(分量)的BFS算法
算法实现讨论
- 与DFS类似,同样要设访问标志数组visited[ ]。
- 为了能依次访问上一层次的访问序列中的各顶点的邻接点,需要设置一个结构來保存上一层次的顶
点,即刚刚被访问过且其后继邻接点还未被访问的顶点,并且这一结构还要满足这样的条件:这一
层中最先被访问的顶点,其后继邻接点也应被最先访问到。由此可知,这一结构应是队列。 - 既然涉及到队列(不妨设为Q),则需要在适当的情况下操作队列:
(a)初始化:开始时要设置队列Q为空;
(b)入队:每访问一个顶点v,除了访问操作、设置标志外,还要将其入队。在此不妨设为enQueue(v)。
(c)出队:取队头元素v,不妨用getFront(v),队头出队,然后要依次访问v的所有未被访问过的邻接点。求解v的邻接点,方法与DFS相同。 - 综上所述,可将BFS(v)细化如下:
- 初始化队列Q;
- 访问v(包括三个操作:访问v,设置标志,入队)
- 若队列Q为空,则结束BFS(v),否则,转4
- v=Q.getFront(Q); Q.oueQueue()
- w=v的第一邻接点 //依次访问v的未被访问的邻接点
- 若w未被访问过,则访问w(同样包括访问w,设置标志,入队这三个操作)
- w=v的下一个邻接点,若不存在,转3
- 转6
BFS算法描述
// An highlighted block
//从指定编号为v的顶点出发广度遍历
void BFS(Graph G,int v)
{
int w;
Queue Q; //初始化队列
visit(v); //访问顶点v
visited[v] = TRUE; //访问顶点v已访问
enQueue(Q,v); //v入队
while(!queueEmpty(Q))
{
getFront(Q,v); //取队头元素到v
outQueue(Q); //队头元素出队
w = firstAdj(G,v); //查找v的第一个邻接点
while(w!=0) //循环搜索v的每一个邻接点
{
if(!visited[w]) //邻接点w未被访问
{
visit(G,w); //访问顶点w
visited[w] = TRUE; //标记顶点w已经访问
enQueue(Q,w); //w入队
}
w = nextAdj(G,v,w); //查找顶底v的在w之后的下一个邻接点
}
}
}
一般图的(通用)BFS算法
算法描述
// An highlighted block
void BFSTraverse( Graph G, int v )
{
int i;
for (i=1; i<=n; i++)
visited[i]=FALSE;
//广度优先遍历指定起点v的连通分量
BFS(G,v);
for (i=1; i<=n; i++)
if( !visited[i] )
BFS( G, i );
//每执行一次BFS(i),广度遍历一个连通分量
}
连通图(分量)BFS的实现
(1) BFS基于邻接矩阵的实现参考
// An highlighted block
void BFS(Graph G,int v)
{
Queue<int,100> Q; //初始化队列
visit(v); //访问顶点v
visited[v] = TRUE; //标记顶点V已经访问
Q.enQueue(v); //编号为v的顶点入队
int u ;
while(!Q.empty()) //队列不空循环处理顶点
{
Q.getFront(u); //取队头元素到u,即顶点编号为U
Q.outQueue(); //u出队
for(int w=1;w<=VerNum;w++)
{ //循环处理u的每个未访问的邻接点
if((AdjMatrix[u][w]>=1) && (AdjMatrix[u][w]<=INF) && (!visited[w]))
{
visit(w); //访问顶点w
visited[w] = TRUE; //标记w已经访问
Q.enQueue(w); //编号w的邻接点入队
}
}
}
}
(2)BFS基于邻接表的实现参考
// An highlighted block
void Graph::BFS(int v)
{
int u; //顶点编号
EdgeNode *p; //边链表结点指针
Queue<int,100> Q; //初始化队列
visit(v); //访问编号为v的顶点
visited[v]=true; //标记顶点v已经访问
Q.enQueue(v); //编号v入队
while( !Q.empty() ) //队列不空循环处理顶点
{
Q.getFront(u); //取队头元素到u,即顶点编号为u。
Q.outQueue(); //u出队
p=VerList[u].firstEdge; //获取当前顶点u边链表的头指针
while( p )
{
if( !visited[p->adjVer] )
{ //p->adjVer为邻接点编号,访问此结点
visit(p->adjVer);
//标记顶点p->adjVer已经访问
visited[p->adjVer]=true;
Q.enQueue(p->adjVer); //顶点p->adjVer入栈
}
p=p->next; //移动到下一条边,即找到下一个邻接点
}
}
}