【数据结构】采用邻接表存储结构,编写一个判别无向图中任意给定的两个结点之间是否存在一条长度为k的简单路径的算法。

编程题:

一、采用邻接表存储结构,编写一个判别无向图中任意给定的两个结点之间是否存在一条长度为d的简单路径的算法。

(一条路径为简单路径指的是其顶点序列中不含有重现的顶点
分析:
本题采用基于递归的深度优先遍历算法,从i 结点出发,递归深度有限遍历图中结点,若访问到结点 j , 且长度符合要求,返回真。k是所求的路径长度。

#define MAX_VERTEX_NUM 100

void DFS(ALGraph G, int i, int j, int k,int visited[],bool Result){
	static int d = 0;//记录当前路径的长度
	visited[i] = 1;  //访问标记
	d++;  
	if (i == j && d == k + 1)//找到一条路径,Result 为真
		Result = true;
	else{
		ArcNode* p;
		p = G.vertices[i].firstarc;  //指针指向第一个邻接点
		while (!Result && p != NULL){
			int w = p->adjvex;    // 若w结点未访问,递归的访问它
			if (visited[w] == 0){
				DFS(G, w, j, k,visited ,Result);
			}	
			p = p->nextarc;
		}
	}
	visited[i] = 0;//回退操作
	d--;
}

int SimplePath(ALGraph G, int i, int j, int k)
{
	static bool Result = false;
	static int visited[MAX_VERTEX_NUM];
	for (int a = 1; a <= G.vexnum; a++)
		visited[a] = false;
	DFS(G, i, j, k,visited,Result);
	return Result;
}

二、假设图用邻接表表示,设计一个算法,输出从顶点vi 到 vj 的所有简单路径。

分析:
本题采用基于递归的深度优先遍历算法,从a结点出发,递归深度有限遍历图中结点,若访问到结点b,则输出该搜索路径上的结点。所以我们可以设置一个数组用来存放路径上的结点(初始为空),d 表示路径长度(初始值-1)。

void FindPath(ALGraph* G, int a, int b, int path[], int d) {
	int w; // 中间变量
	ArcNode* p; 
	d++;     // 路径长度增加1
	path[d] = a; // 将当前节点加入到路径中
	visited[a] = 1;// 已访问标记
	if (a == b ) {   // 找到一条路径
		printf(path[]);  // 进行输出路径
	}
	p = G->adjlist[a].firstarc;  // p 指针指向 a 第一个相邻点
	while (p != NULL) {  // 当指针不为空时
		w = p->adjvex;    // 若w结点未访问,递归的访问它
		if (visited[w] == 0) {
			FindPath(G, w, b, path, d);
		}
		p = p->nextarc;  // p指向a的下一个相邻点
	}
	visited[a] = 0;   //恢复访问权限,该节点可以重新使用了
}

举一反三:
三、采用邻接表存储结构,描述 判断无向图中任意给定的两个结点之间是否存在一条长度为d的简单路径的算法过程。(存在即输出此路径)

判断无向图1 —> 6 ,d 为3的路径是否存在,存在的话并输出
在这里插入图片描述
在这里插入图片描述

算法思想解读:
由图直观可知,所求路径只有一条,1—>4 —>5—>6。
但是在程序运行的过程并不是这么简单,根据邻接表所示,1的邻接点是2,4,5. 算法过程:

1、将节点1加入路径,长度进行加一,(visited 【1】=1 )访问第一个邻接点2。

2、访问结点2(visited【2】= 1),长度加一,并将结点2加入路径,进行递归结点2 。

3、访问结点2的第一个邻接点1,由于结点1的visited 值为1 (访问过得状态),所以访问下一个结点3,长度加一,并将3加入路径,递归结点3。

4、访问结点3(visited【3】 =1 ) ,它的邻接点只有2 并且是被访问过的,所以p 指针访问3的下一个邻接点(为空),跳出while循环,将visited【3】=0 ,并删除路径中的节点三,长度减一。

5、结点2,此时的邻接点也访问结束了,p指向空,跳出while循环,将visited【2】=0 ,并删除路径中的结点2,长度减一。(此时相当于把左边的部分访问完了,回溯到结点1了,长度还是只有节点1,路径中也只有节点1,下一步访问节点1 的下一个邻接点(4))

6、访问结点4的过程同上,递归结点4。

7、简要叙述剩余流程,访问4的邻接点1(访问过),接着访问5,递归5, 5——>1 ,5——>4 都不行,访问结点6 ,节点6即为所求终点,此时路径中包含1、4、5、6,长度为3 ,即为所求,进行输出路径。若不满足,则输出未找到(比如下面8)。

8、如果说结点1的邻接点中 结点5在结点4之前,则进行递归结点5,当访问到结点6时,虽然是所求,但是此时长度为2,不满足题意,则回溯到节点一的下一个邻接点,直到访问结束。

你能理解是我最大的荣幸,有帮助到你就点个赞吧。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值