深度优先遍历(Depth First Search)

深度优先遍历类似于树的先序遍历

1.深度优先搜索遍历连通图

在无向图中任意两个顶点都是连通的(可以不是直接相连),则称该图为连通图

假设从顶点 V 1 V_1 V1出发,访问序列为
V 1 → V 2 → V 3 → V 4 → V 3 ( 已 访 问 ) → V 5 V_1 \rightarrow V_2 \rightarrow V_3 \rightarrow V_4 \rightarrow V_3(已访问) \rightarrow V_5 V1V2V3V4V3(访)V5

bool visited[MVNum];	//标记顶点是否被访问过,其初值为"false"
void DFS(Graph G, int n){	//传入有n个顶点的连通图G
	cout << v;	//输出图中某个顶点在数组中的下标
	visited[v]=true;	//访问第v个顶点,并置访问标志数组相应值为true
	for(w=FirstAdjVex(G,v); w>=0; w=NextAdjVex(G,v,w))	//这里的FirstAdjVex和NextAdjVex没有具体展开。如果图的存储结构不同,这两个的实现方法不同
	//依次检查v的所有邻接点w
	//FirstAdjVex(G,v)表示v的第一个邻接点
	//w>=0表示存在邻接点
	//NextAdjVex(G,v,w)表示v的相对于w的下一个邻接点
		if(!visited[w])
			DFS(G,w);	//对v的尚未访问的邻接顶点w递归调用DFS
}

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);		//对未访问的顶点进行访问
}

3.深度优先搜索遍历以结构为邻接矩阵的图

无向图

有向图

DFS只是对通道是否存在进行判断,对无向图和有向图算法上没有变化,完全通用

void DFS_AM(AMGraph G, int v){	//传入有向/无向图、第一个要访问的顶点在一维数组中的下标
	cout << v;	//输出某个顶点在一维数组中的下标
	visited[v]=true;	//访问第v个顶点,并置访问标志数组相应值为true
	for(w=0; w<G.vexnum; w++)	//依次检查邻接矩阵v所在行
		if((G.arcs[v][w] != 0) && (!visited[w]))
			DFS_AM(G,w);	//递归遍历未访问的顶点
}

4.深度优先搜索遍历以结构为邻接表的图

无向图

有向图

void DSL_AL(ALGraph G, int v){
	cout << v;	//输出某个顶点在一维数组中的下标
	visited[v]=true;	//访问第v个顶点,并置访问标志数组相应值为true
	p=G.vertices[v].firstarc;	//将下标为v的顶点的第一邻接点指针域命名为p
	while(p != NULL){	//下标为v的顶点的第一邻接点非空
		w=p->adjvex;	//p所指结点的数据域,该数据域是顶点在一维数组中的下标,将该下标赋值给w
		if(!visited[w])	//下标为w的顶点未访问过
			DSL_AL(G,w);	//递归遍历
		p=p->nextarc;	//现在用p指向p->nextarc所指的结点,以便下一次遍历时使用p
	}
}
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐