【数据结构】采用邻接表存储结构,编写一个判别无向图中任意给定的两个结点之间是否存在一条长度为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
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是采用深度优先搜索算法实现的判别无向图任意给定两个顶点之间是否存在一条长度为k的简单路径算法。其邻接表存储结构使用了结构体数组和链表。 ```c #include <stdio.h> #include <stdlib.h> #define MAX_VERTEX_NUM 100 // 最大顶点数 #define FALSE 0 #define TRUE 1 typedef struct ArcNode { // 邻接表结点的类型 int adjvex; // 该边所指向的顶点的位置 struct ArcNode *nextarc; // 指向下一条边的指针 } ArcNode; typedef struct VertexNode { // 邻接表顶点结点的类型 int data; // 顶点信息 ArcNode *firstarc; // 指向第一条依附该顶点的边的指针 } VertexNode; typedef struct { // 邻接表的类型 VertexNode vertices[MAX_VERTEX_NUM]; // 顶点数组 int vexnum, arcnum; // 图的当前顶点数和边数 } ALGraph; int visited[MAX_VERTEX_NUM]; // 访问标志数组 // 创建邻接表 void CreateALGraph(ALGraph *G) { int i, j, k; ArcNode *p; printf("请输入顶点数和边数(空格隔开):"); scanf("%d %d", &G->vexnum, &G->arcnum); for (i = 0; i < G->vexnum; ++i) { printf("请输入第%d个顶点信息:", i + 1); scanf("%d", &G->vertices[i].data); G->vertices[i].firstarc = NULL; } for (k = 0; k < G->arcnum; ++k) { printf("请输入边(vi,vj)的下标i和j及其边权值w(空格隔开):"); scanf("%d %d", &i, &j); p = (ArcNode *)malloc(sizeof(ArcNode)); p->adjvex = j; p->nextarc = G->vertices[i].firstarc; G->vertices[i].firstarc = p; p = (ArcNode *)malloc(sizeof(ArcNode)); p->adjvex = i; p->nextarc = G->vertices[j].firstarc; G->vertices[j].firstarc = p; } } // 深度优先搜索算法 int DFS(ALGraph *G, int v, int w, int k) { int flag = FALSE; if (k == 0) { // 到达目标深度 if (v == w) // 判断是否为目标顶点 flag = TRUE; } else { visited[v] = TRUE; // 将当前顶点标记为已访问 ArcNode *p = G->vertices[v].firstarc; while (p && !flag) { // 遍历当前顶点的所有邻接顶点 if (!visited[p->adjvex]) // 如果邻接顶点未被访问过 flag = DFS(G, p->adjvex, w, k - 1); p = p->nextarc; } visited[v] = FALSE; // 恢复当前顶点的未访问状态 } return flag; } // 判断无向图任意给定两个顶点之间是否存在一条长度为k的简单路径算法 int ExistSimplePath(ALGraph *G, int u, int v, int k) { int i; if (u < 0 || u >= G->vexnum || v < 0 || v >= G->vexnum) // 判断输入的顶点是否合法 return FALSE; if (k <= 0) // 判断输入的深度是否合法 return FALSE; for (i = 0; i < G->vexnum; ++i) visited[i] = FALSE; // 初始化访问标志数组 return DFS(G, u, v, k); // 判断是否存在一条长度为k的简单路径 } int main() { ALGraph G; CreateALGraph(&G); int u, v, k; printf("请输入要判断的两个顶点u和v以及路径长度k(空格隔开):"); scanf("%d %d %d", &u, &v, &k); if (ExistSimplePath(&G, u, v, k)) printf("存在一条长度为%d的简单路径顶点%d到顶点%d\n", k, u, v); else printf("不存在一条长度为%d的简单路径顶点%d到顶点%d\n", k, u, v); return 0; } ``` 在上述算法,先通过CreateALGraph函数建立无向图邻接表,然后在ExistSimplePath函数给定两个顶点u和v以及路径长度k进行判断。接着,在DFS函数实现了深度优先搜索算法,其visited数组用于标记顶点是否被访问过,p指针用于遍历当前顶点的所有邻接顶点。最后,根据DFS函数的返回结果,判断是否存在一条长度为k的简单路径
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值