文章目录
图的遍历大纲
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)
两种遍历方法的不同之处仅仅在于对顶点访问的顺序不同。