广度优先搜索遍历算法

连通图(分量)的BFS算法

算法实现讨论

  1. 与DFS类似,同样要设访问标志数组visited[ ]。
  2. 为了能依次访问上一层次的访问序列中的各顶点的邻接点,需要设置一个结构來保存上一层次的顶
    点,即刚刚被访问过且其后继邻接点还未被访问的顶点,并且这一结构还要满足这样的条件:这一
    层中最先被访问的顶点,其后继邻接点也应被最先访问到
    。由此可知,这一结构应是队列
  3. 既然涉及到队列(不妨设为Q),则需要在适当的情况下操作队列:
    (a)初始化:开始时要设置队列Q为空;
    (b)入队:每访问一个顶点v,除了访问操作、设置标志外,还要将其入队。在此不妨设为enQueue(v)。
    (c)出队:取队头元素v,不妨用getFront(v),队头出队,然后要依次访问v的所有未被访问过的邻接点。求解v的邻接点,方法与DFS相同。
  4. 综上所述,可将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; //移动到下一条边,即找到下一个邻接点
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值