第六章——图(3)图的遍历

图的遍历大纲

1.图的遍历定义

从已给的连通图中某一顶点出发,沿着一些边访遍图中所有的顶点,且使每个顶点仅被访问一次,就叫做图的遍历,它是图的基本运算。

图的遍历的实质:找到每个顶点邻接点的过程。
怎样避免重复访问:
设置辅助数组visited[n],用来标记每个被访问过的顶点
    初始状态:visited[0]
    顶点i被访问visited[1],防止多次被访问

2.深度优先搜索(DFS)

类似于树的先序遍历

2.1深度优先搜索遍历基本思想

对于一个连通图,深度优先搜索遍历的过程如下:
    ①从图中某个顶点v出发,访问v。
    ②找出刚访问过的顶点的第一个未被访问的邻接点,访问该顶点。以该顶点为新顶点,重复此步骤,直至刚访问过的顶点没有未被访问的邻接点为止。
    ③返回前一个访问过的且仍有未被访问的邻接点的顶点,找出该顶点的下一个未被访问的邻接点,访问该顶点。
    ④重复步骤②和③),直至图中所有顶点都被访问过,搜索结束。

2.1深度优先算法实现
2.1.1深度优先搜索遍历连通图

深度优先搜索遍历连通图是一个递归的过程

//深度优先搜索遍历连通图
bool visit[MVNum];  //访问标志组,其初始值为false;
void DFS(Graph G,int v)//从第v个顶点出发递归地深度优先遍历图G
{
	prinf("%d",v);//访问第v个结点
	visit[v]=true;//并置访问标志数组相应分量值为true
	for(w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w))//依次检查v的所有邻接点
	{//FirstAdjVex(G,v)表示v的第一个邻接点;NextAdjVex(G,v,w)表示v相对于w的下一个邻接点,w≥0表示存在邻接点
		

		if(!visited[w])
			DFS(G,w);//对v尚未访问的邻接顶点w递归调用DFS
	}
}

2.1.2深度优先搜索遍历非连通图
//深度优先搜索遍历非连通图
void DFSTraverse(Graph G)//对非连通图G做深度优先遍历
{
	for(v=0;v<G.vexnum;++v)
	{
		visited[v]=false;//访问标志数组初始化
	}
	for(v=0;v<G.vexnum;v++)
	{
		if(!visited[v])//对尚未访问的顶点调用DFS
			DFS(G,v);
	}
}
2.1.3采用邻接矩阵表示图的深度优先搜索遍历
//采用邻接矩阵表示图的深度优先搜索遍历
void DFS_AM(AMGraph G,int v)//图G为邻接矩阵类型,从第v个顶点出发深度优先搜索遍历图G
{
	printf("%d",v);
	visited[v]=true;//访问第v个顶点,并设置访问标志数组相应分量值为true
	for(w=0;w<G.vexnum;w++)//依次检查邻接矩阵v所在的行
	{
		if((G.arcs[v][w]!=0)&&!visited[w]))
			DFS(G,w);//G.arcs[v][w]!=0表示w是v的邻接点,如果w未访问,则递归调用DFS
	}
}
2.1.3采用邻接表表示图的深度优先搜索遍历
void DFS_AL (ALGraph G,int v)//图G为邻接表类型,从第v个顶点出发深度优先搜索遍历图G
{
	printf("%d",v);//访问第v个顶点,并置访问标志数组相应分量值为true
	visited[v]=true;    
	p=G.vertices[v].firstarc;//p指向v的边链表的第一个边结点
	while(p!=NULL)//边结点非空
	{
		  w=p->adjvex;  //表示w是v的邻接点
		  if(!visited[w]) 
			  DFS_AL(G,w);         //如果w未访问,则递归调用DFS_AL
		   p=p->nextarc;         //p指向下一个边结点
	}
}
2.1深度优先搜索遍历的算法分析

①用邻接矩阵表示图时,查找每个顶点的邻接点的时间复杂度为O(n^2);
②邻接表做图的存储结构时,深度优先搜索遍历图的时间复杂度为O(n+e)。
③DFS算法是递归算法,需要借助一个栈,故其空间复杂度为O(n)
结论:
稠密图适合在邻接矩阵上进行深度遍历
稀疏图适合在邻接表上进行深度遍历
在这里插入图片描述

3.广度优先搜索(BFS)

广度优先搜索(Breadth First Search,BFS)遍历类似于树的按层次遍历的过程

3.1广度优先搜索遍历基本思想

    ①从图中某个顶点v出发,访问v。
    ②依次访问v的各个未曾访问过的邻接点。
    ③分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问。重复步骤③,直至图中所有已被
访问的顶点的邻接点都被访问到。
在这里插入图片描述
广度优先搜索是一种分层的查找过程,每向前走一步可能访问一批顶点,不像深度优先搜索那样有往回退的情况,因此它不是一个递归的算法。为了实现逐层访问,算法必须借助一个辅助队列,以记忆正在访问的顶点的下一层顶点。

2.2广度优先算法实现
void BFS(Graph G,int v)
{
	printf("%d",v);//访问第v个顶点,并置访问标志数组相应分量值为true
	visited[v]=true;    
	InitQueue(Q); //辅助队列Q的初始化,置空
	EnQueue(Q,v);//v进队
	while(!isEmpty(Q))
	{
		DeQueue(Q,v);//顶点v出队
		for(w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w))//检测v所有的邻接点
		{
			if(!visit[w])//w为v尚未访问的邻接顶点
			{
				visit[w]=true;//对访问的w做已访问的标记
				EnQueue(Q,w);//顶点w入队
			}
		}
	}
}

若是非连通图,上述遍历过程执行之后,图中一定还有顶点未被访问,需要从图中另选一个未被访问的顶点作为起始点,重复上述广度优先搜索过程,直到图中所有顶点均被访问过为止。

2.2广度优先搜索遍历的算法分析

因此广度优先搜索遍历图的时间复杂度和深度优先搜索遍历相同:
①用邻接矩阵存储时,时间复杂度为O(^2);
②用邻接表存储时,时间复杂度为O(n+e)。
③BFS算法是递归算法,需要借助一个栈,故其空间复杂度为O(n)
两种遍历方法的不同之处仅仅在于对顶点访问的顺序不同。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值