图的遍历 深度优先遍历 广度优先遍历

图的遍历和树的遍历类似的,从图中某一顶点出发遍访图中其余顶点,且使每个顶点只被访问一次,这个过程叫做图的遍历。

图那么复杂,因为它的任一顶点都可能和其余的所有顶点相邻接,极有可能存在沿着某条路径搜索后,又回到原顶点,而有些顶点却还没有遍历到的情况。因此我们需要在遍历过程中把访问过的顶点打上标记,以避免访问多次而不自知。具体办法是设置-一个访问数组 visited[n], n是图中顶点的个数,初值为0,访问过后设置为1。

对于图的遍历来说,如何避免因回路陷入死循环,就需要科学地设计遍历方案,通常有两种遍历次序方案:它们是深度优先遍历和广度优先遍历。

深度优先遍历

深度优先遍历(Depth_First_Search),也有称为深度优先搜索,简称为DFS。

深度优先遍历其实就是一个递归的过程,如果再敏感一些,会发现其实转换成如图 的右图后,就像是一棵树的前序遍历,没错,
它就是。它从图中某个顶点v出发,访问此顶点,然后从v的未被访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到。事实上,我们这里讲到的是连通图,对于非连通图,只需要对它的连通分量分别进行深度优先遍历,即在先前一个顶点进行一次深度优先遍历后,若图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。

如果我们用的是邻接矩阵的方式,代码如下:

typedef int Boolean;	// Boolean是布尔类型,其值是TRUE或FALSE
Boolean visited[MAX];	//访问标志的数组

/*邻接矩阵的深度优先递归算法*/
void DFS(MGraph G, int i)
{
	int j;
	visited[i] = TRUE;
	printf("%c",G.vexs[i]);//打印顶点, 也可以其他操作
	for (j = 0; j < G.numvertexes; j++)
		if (G.arc[i][j] == 1 && !visited[j])
			DFS(G,j);		//对为访问的邻接顶点递归调用 
}

/*邻接矩阵的深度遍历操作*/
void  DFSTraverse(MGraph G)
{
	int i;
	for (i = 0; 1 < G.numvertexes; i++)
		visited[i] = FALSE;		// 初始所有顶点状态都是未访问过状态
	for (i = 0; i < G.numVertexes; i++)
		if (!visited[i])		//对未访问过的顶点调用DFS,若是连通图,只会执行一次
			DFS(G, 1);
}

广度优先遍历

广度优先遍历(Brcadth_First Search), 又称为广度优先搜索,简称BFS。广度优先遍历借助队列完成。

如果说图的深度优先遍历类似树的前序遍历,那么图的广度优先遍历就类似于树的层序遍历了。我们将下图的第一幅图稍微变形,变形原则是顶点A放置在最上第一层,让与它有边的顶点B、F为第二层,再让与B和F有边的顶点C、1、G、E为第三层,再将这四个顶点有边的D、H放在第四层,如图7-5-3的第二幅图所示。此时在视觉上感觉图的形状发生了变化,其实顶点和边的关系还是完全相同的。

邻接矩阵的广度优先遍历算法

void BFSTraverse(MGraph G)
{
	int i, j;
	Queue Q;
	for (i = 0; i < G.numVertexes; i++)
		visited[i] = FALSE:
	InitQueue(&Q);		//初始化一辅助用的队列
	for (i = 0; i < G.numVertexes; i++) //对每一个顶点做循环
	{
		if (!visited[i])		//若是未访问过就处理
		{
			visited[1] = TRUE;	//设置当前顶点访问过
			printf("%c ",G.vexs[i]);//打印顶点
			EnQueue(&Q, i);		//将此顶点入队列
			while (!QueueEmpty(Q)) //若当前队列不为空
			{
				DeQueue(&Q, &i);	//将队中元素出队列,赋值给i
				for (j = 0; j < G.numVertexes; j++)
				{
					//断其他顶点若与当前顶点存在边且未访问过 
					if (G.arc[i][j] == 1 && !visited[j])
					{
						visited[j] = TRUE;	//将找到的此顶点标记为已访问
						printf("%c ", G.vexs[j]); //打印顶点
						EnQueue(&Q, j);			//将找到的此顶点入队列
					}
				}
			}
		}
	}
}

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值