C语言数据结构基础 图的深度优先遍历

        图作为一种复杂的数据结构,也存在遍历问题。图的遍历就是从图中的某个顶点出发,按某种方法对图中的所有顶点访问且仅访问一次,图的遍历算法是求解图的连通性问题,拓扑排序和关键路径等算法的基础。

        图的遍历比起树的遍历要复杂得多。由于图中顶点关系是任意的,即图中顶点之间是多对多的关系,图可能是非连通图,图中还可能存在回路,因此在访问了某个顶点后,可能沿着某条路径搜素后又回到该顶点上。为了保证图中的各顶点在遍历过程中,访问且仅访问一次,需要为每个顶点设一个访问标志,因此要为图设置一个访问标志数组visited[n],用于标示图中每个顶点是否被访问过,它的初值为0(假),一旦顶点vi访问过,则置visited[i]为1(真),以表示该顶点已访问。

        对于图的遍历,通常有两种方法,即深度优先搜索和广度优先搜素。这两种遍历方法对于无向图和有向图均适用。

一.深度优先搜索

        深度优先搜索(Depth-First Search,DFS)是指按照深度方向搜索,它类似于树的先根遍历,是树的先根遍历的推广。

        深度优先搜素的基本思路:

        ① 从图中某个顶点v0出发,首先访问v0.

        ② 找出刚访问过的顶点的第一个未被访问的邻接点,然后访问该顶点。 以该顶点为新顶点,重复刚才的步骤,直到刚访问过的顶点没有未被访问过的邻接点为止。 此时就有两种情况,直接访问完了,说明整个就是连通图。如果此图还有其余结点未被访问,说明该图存在连通分量。

        ③ 返回前一个访问过的且仍有未被访问的邻接点的顶点,找出该顶点的下一个未被访问的邻接点,访问该顶点,然后执行步骤②。

        

01-1.算法思想

        ① 访问出发点v0

        ② 依次以v0未被访问的邻接点为出发点,深度优先搜索图,直到图中所有与v0有路径相通的顶点被访问。

        若此图为非连通图,从剩余顶点中找未被遍历的,重复上述操作。

01-2.代码实现:

        以邻接链表为例:

// 深度优先搜索
// DFS
// 在图AL中,以v为起点开始遍历,然后一直向下遍历,直到这条路径到头,开始回溯到上个顶点,寻找该顶点尚未遍历的路径
// 02-深度优先搜索
void Depth_First_Search(AdjList* AL, DataType v) {
	// 首先要对已经输出的顶点做个标记,可以在数据区新开标记,或者搞个静态数组来存放顶点状态,0未,1已
	static int Flag[M] = { 0 };
	// 其次能够在回溯时找到上一个顶点, 这里用栈或者递归实现
	VertexNode node = AL->vertexs[LocateVertex(AL, v)]; // 尾
	if (Flag[LocateVertex(AL, v)] == 0) {
		printf("%c ", node.vertex);
	}
	Flag[LocateVertex(AL, v)]++;  // 打上记号
	// ArcNode * arc = AL->vertexs[LocateVertex(AL, v)].arc;
	ArcNode* arc = node.arc;  // 头
	while (arc != NULL) {  // 在一个顶点的邻接点中找
		if (Flag[LocateVertex(AL, arc->arc)] == 0) { // 找到还没遍历的顶点
			Depth_First_Search(AL, arc->arc);       // 从新结点开始找
		}
		arc = arc->next;
	}
	// 连通图,都找完了就是完了
}

还可以据此改进,判断此图是否连通,不连通的话,连通分量是多少

// 连通性
// 此图未必连通,就会存在多个开始的顶点 所以要存放每个连通分量的路径 但每个路径长度不同,所以用链表存好
DataType* Path[M];
void Depth_First_Search_UP(AdjList* AL, DataType v,int Flag[]) {
	// 首先要对已经输出的顶点做个标记,可以在数据区新开标记,或者搞个静态数组来存放顶点状态,0未,1已
	//static int Flag[M] = { 0 };
	// 其次能够在回溯时找到上一个顶点, 这里用栈或者递归实现
	VertexNode node = AL->vertexs[LocateVertex(AL, v)]; // 尾
	if (Flag[LocateVertex(AL, v)] == 0) {
		printf("%c ", node.vertex);
	}
	Flag[LocateVertex(AL, v)]++;  // 打上记号
	// ArcNode * arc = AL->vertexs[LocateVertex(AL, v)].arc;
	ArcNode* arc = node.arc;  // 头
	while (arc != NULL) {  // 在一个顶点的邻接点中找
		if (Flag[LocateVertex(AL, arc->arc)] == 0) { // 找到还没遍历的顶点
			Depth_First_Search_UP(AL, arc->arc,Flag);       // 从新结点开始找
		}
		arc = arc->next;
	}
	
}

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值