数构之图的遍历

图的遍历

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

  • 深度优先搜索
  • 广度优先搜索
    在这里插入图片描述
深度优先搜索(DFS):

图的深度优先搜索类似于二叉树的先序遍历。

在深度优先搜索中,对于最新发现的顶点,如果它还有以此为起点而未探测到的边,就沿此边继续探测下去。当顶点 v
的所有边都已被探寻过后,搜索将回溯到发现顶点 v
有起始点的那些边。这一过程一直进行到已发现从源顶点可达的所有顶点为止。实际上深度优先搜索最初的探究也是为了解决迷宫问题。
在这里插入图片描述

深度优先搜索的思想:

  1. 首先访问出发点v,并将其标记成已访问过;
  2. 然后选取与v邻接的未被访问的任意一个顶点w,并访问它;
  3. 再选取与w邻接的未被访问的任意一个顶点并访问;
  4. 重复进行;
  5. 当一个顶点所有的邻接顶点都被访问过,则依次退回最近被访问过的顶点;
  6. 若该顶点还有其他邻接顶点未被访问,则从这些未被访问的顶点中取一个并重复上述过程;
  7. 直至图中所有的顶点都被访问过为止;

无向图的深度优先遍历:
在这里插入图片描述

  • 首先访问出发点A,并将其标记为已访问。
  • 访问(A的邻接顶点)C.
    由图可知A的邻接顶点有C.D.F。
  • 访问(C的邻接顶点)B.
  • 访问(C的邻接顶点)D.
  • 访问(A的邻接顶点)F.

前面已经访问了A,并且访问完了A的邻接点C的所有邻接点(包括递归的邻接点在内);因此,此时返回到访问A的另一个邻接点F。

由图可知F的邻接顶点是A和G,A已访问。

  • 访问(F的邻接顶点)G.
    G的邻接顶点为F和E,F已访问。
  • 访问(G的邻接顶点)E.在这里插入图片描述
    因此访问顺序是:A -> C -> B -> D -> F -> G -> E

有向图的深度优先遍历:
在这里插入图片描述

  • 访问A。
  • 访问(A的出边顶点)B
  • 访问(B的出边顶点)C
    在访问了B之后,接下来应该访问的是B的出边顶点,即顶点C,E,F。
  • 访问(B的出边顶点)E
    接下来访问C的出边的另一个顶点,即顶点E。
  • 访问(E的出边顶点)D
    接下来访问E的出边的另一个顶点,即顶点B,D。顶点B已访问,因此访问顶点D。
  • 访问(B的出边顶点)F
  • 访问(F的出边顶点)G
    在这里插入图片描述

因此访问顺序是:A -> B -> C -> E -> D -> F -> G

算法执行过程:任取一个顶点,访问,然后检查这个顶点的所有邻接顶点,递归访问其中未被访问过的顶点。

图的遍历结果取决于图的存储结构

图的邻接矩阵是唯一的,但对于邻接表来说,如果边的输入次序不同,邻接表也不同,

  1. 因此对于同一个图,基于邻接矩阵的遍历所得的DFS序列和BFS序列是唯一的;
  2. 基于邻接表的遍历所得到的DFS序列和BFS序列是不唯一的 。
    深度优先的算法分析
    在遍历过程中,一个顶点至多调用一次DFS函数,如果一旦某个顶点标志为已访问,就不再从它出发进行搜索

⑴ 利用邻接矩阵作为图的存储结构时, 查找每个顶点的
邻接点所需要时间为O(n²),其中为n顶点数。
⑵ 利用邻接表作为图的存储结构时, 找邻接点所需要的时间为O(e);因此,总的时间复杂度为O(n+e)

算法过程:

Boolean visited[MAX];                //  访问标志数组
Status (*VisitFunc)(int v);//  指向函数的指针
void  DFSTraverse(Graph G,Status(*Visit)(int V))
{  //  对图G作深度优先遍历
	VisitFunc=Visit; //  使用全局变量VisitFunc,使DFS不必设函数指针参数
		for(v=0;v<G.vexnum;++v)
		visited[v]=FALSE;                 //  访问标志数组初始化
		for(v=0;v<G.vexnum;++v)    // 本代码从v=0开始遍历
		if(!visited[v])
		DFS(G,v);        //  对未访问的结点调用DFS
}
void   DFS(Graph G,int V)
{
	//  从第v个顶点出发递归地深度优先遍历图G
	visited[v]=TRUE;
		VisitFunc(v);   //  访问第v个顶点
		for(w=FirstAdjVex(G,v); w>=0;w=NextAdjVex(G,v,w))
		if(!visited[w])
		DFS(G,w);    //  对v的未访问的邻接顶点w递归调用DFS
}
广度优先搜索遍历(BFS)

图的广度优先搜索遍历类似于树的层次遍历。

层序遍历
概念:先遍历第一层,再遍历第二层,…
特点:思想简单,实现复杂

在这里插入图片描述
访问过程:

  • 首先A入列。
    访问A,A已访问,A出列

  • (A的邻接顶点)B、F入列
    访问B,B已访问,B出列

  • (B的邻接顶点)C、I、G入列
    访问F,F已访问,F出列

  • (F的邻接顶点)E入列
    访问C,C已访问,C出列

  • (C的邻接顶点)D入列
    访问I,I已访问,I出列
    访问G,G已访问,G出列
    访问E,E已访问,E出列

  • (E的邻接顶点)H入列
    访问H,H已访问,H出列

void BFSTraverse(Graph G,Status(*Visit)(int v))
{//  使用访问标志数组visited和辅助队列Q

	for(v=0;v<G.vexnum;++v) 
		visited[v]=FALSE;//  访问标志数组初始化
	InitQueue(Q); //  置空的辅助队列Q
	for(v=0;v<G.wexnum;++v)//从0号顶点开始遍历
		if(!visited[v])
		{
			visited[v]=TRUE;
			Visit(v);
			EnQueue(Q,v);
			while(!QueueEmpty(Q))
			{
				DeQueue(Q,u); //  队头元素出队并置为u
				for(w=FirstAdjVex(G,v);
					w>=0;w=NextAdjVex(G,u,w))
					if(!visited[w]) //  w为v的尚未访问的邻接顶点
					{
						visited[w]=TRUE;
						Visit(w);
						EnQueue(Q,w);
					}
			}
		}
}

好啦,下次等我做了习题再来更新。留给赞吧~
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值