求最短路径

设计山河大学的校园平面图,所含景点不少于 8 个。以图中顶点表示学校内各景点,存放景点的名称、景点介绍信息等;以边表示路径,存放路径长度信息。要求将这些信息保存在文件 graph.txt 中,系统执行时所处理的数据要对此文件分别进行读写操作。
1.从文件 graph.txt 中读取相应数据, 创建一个图,使用邻接矩阵表示图;
2.景点信息查询:为来访客人提供校园任意景点相关信息的介绍;
3.问路查询:为来访客人提供校园任意两个景点之间的一条最短路径。
选做内容(对文件进行操作,相应信息变化后,再次进行景点信息查询和问路查询时应该有所体现)

  1. 修改一个已有景点的相关信息;
  2. 增加一个新景点及其相关信息;
  3. 增加一条新的路径;
  4. 删除一个景点及其相关信息;
  5. 删除一条路径
    地图:

在这里插入图片描述

8,15
图书馆 读书
男生宿舍 住男生
女生宿舍 住女生
食堂 吃饭
体育馆 锻炼
广场 玩耍
校门口 出校
教学楼 学习
图书馆 教学楼 200
男生宿舍 图书馆 500
女生宿舍 图书馆 400
男生宿舍 女生宿舍 1600
图书馆 校门口 900
图书馆 广场 350
图书馆 体育馆 400
男生宿舍 食堂 450
男生宿舍 体育馆 450
女生宿舍 校门口 1650
男生宿舍 广场 780
女生宿舍 广场 950
教学楼 男生宿舍 540
教学楼 女生宿舍 650
教学楼 食堂 900



```c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MaxInt 32762   //表示极大值
#define OK 1
#define ERROR 0
#define MAXSIZE 100   //数组空间
typedef int Status;      //函数返回值类型
//顶点结构
typedef struct {
	char name[100];    //顶点名字
	char info[100];    //顶点相关信息
}VerTexType; 
//邻接矩阵结构
typedef struct Graph
{
	VerTexType vexs[MAXSIZE];//顶点表
	int arcs[100][100];  //邻接矩阵
	int vexnum, arcnum;//图的当前点数和边数
}AMGraph;
//
//求该顶点位置
int LocateVex(AMGraph G, char u[])
{
	for (int i = 0; i < G.vexnum; ++i)  
		if (strcmp(u, G.vexs[i].name) == 0)//注意字符串判断相等
			return i;
	printf("cannot find\n");
	return -1;
}
//创建无向网
void CreatUDN(AMGraph &G)
{
	FILE*fp;                    //取文件数据
	int v0, v3, v4;             //记录起点、终点位置
	int i, j, k;               //循环计次
	char v1[20], v2[20];            //暂储顶点名字和相关信息
	int w;                        //暂存权值
	fp = fopen("Graph.dat", "r");
	fscanf(fp, "%d,%d", &G.vexnum, &G.arcnum);   //输入总顶点数,总边数
	for (i = 0; i < G.vexnum; ++i)
		fscanf(fp, "%s %s", &G.vexs[i].name, &G.vexs[i].info);//依次输入顶点信息

	for (i = 0; i < G.vexnum; ++i)
		for (int j = 0; j < G.vexnum; ++j)
			G.arcs[i][j] = MaxInt;//初始化邻接矩阵
	for (k = 0; k < G.arcnum; ++k)
	{
		fscanf(fp, "%s %s %d", v1, v2, &w);   //输入一条边依附的顶点及权值
		i = LocateVex(G, v1); j = LocateVex(G, v2);//确定v1,v2在G中的位置
		G.arcs[i][j] = w;//边的权值置为w
		 G.arcs[j][i]=w;//对称边也置为w
	}
	fclose(fp);
}
//栈
typedef int SElemType;   //栈中存放的数据类型
//栈存储结构
typedef struct
{
	SElemType *base;    //栈底指针
	SElemType *top;     //栈顶指针
	int stacksize;      //栈可用最大容量
}SqStack;
//栈的初始化
Status InitStack(SqStack &S)
{
	S.base = new SElemType[MAXSIZE];
	if (!S.base)return ERROR;
	S.top = S.base;
	S.stacksize = MAXSIZE;
	return OK;
}
//入栈
Status Push(SqStack &S, SElemType e)
{
	if (S.top - S.base == S.stacksize - 1)return ERROR;
	*S.top++ = e;
	return OK;
}
//出栈
Status Pop(SqStack &S, SElemType &e)
{
	if (S.top == S.base)return ERROR;
	e = *--S.top;
	return OK;
}
//取栈顶元素
SElemType GetTop(SqStack S)
{
	if (S.top - S.base == S.stacksize) return ERROR;
	else return *(S.top - 1);
}

//迪杰斯特拉算法
void ShortestPath_DIJ(AMGraph G, int v0, int Path[100],int D[100])//v0为源点,Path[]数组记录最短路径,D[]记录最短路径长度
{
	int n;       //记录顶点总数
	int i, v, w; //循环计数
	int min;    //记录最小值
	int S[100];  //记录顶点是否确定最短路径
	n = G.vexnum;
	for (v = 0; v < n; ++v)//n个顶点依次初始化
	{
		S[v] = 0;                     //初始化为空集
		D[v] = G.arcs[v0][v];              //将v0到个各终点的最短路径长度初始化为弧上的权值
		if (D[v] < MaxInt)Path[v] = v0;   //有弧v0
		else Path[v] = -1;                 //无弧为-1
	}
	S[v0] = true;                      //v0加入S
	D[v0] = 0;                       //源点到源点的距离为0
	/*                  初始化结束,开始主循环,每次求得v0到某个顶点v的最短路径,将v加入S                                       */
	for (i = 1; i < n; ++i)
	{
		min = MaxInt;
		for (w = 0; w < n; ++w)
			if (!S[w] && D[w] < min)//选择一条最短路径,终点为v
			{
				v = w;
				min = D[w];
			}
		S[v] = true;                //将v加入S
		for (w = 0; w < n; ++w)     //更新从v0出发到集合V-S上所有顶点的最短距离
			if (!S[w] && (D[v] + G.arcs[v][w] < D[w]))
			{
				D[w] = D[v] + G.arcs[v][w];    //更新D[w]
				Path[w] = v;                     //更改w的前驱为v
			}
	}
}

//增加一个顶点及其相关信息
Status InsertVex(AMGraph &G,char v[],char v1[])
{
	int n; n = G.vexnum;
	if ((G.vexnum + 1) > MAXSIZE)//判断顶点数量是否超额
		return ERROR;
	G.vexnum++;
	strcpy(G.vexs[n].name,v); //将景点名字及相关信息输入
	strcpy(G.vexs[n].info, v1);
	for (int k = 0; k < G.vexnum; k++)//将矩阵中相关数据初始化
		G.arcs[n][k] = G.arcs[k][n] = MaxInt;
	return OK;
}
//增加一条边
Status InsertArc(AMGraph &G, char v[], char v1[],int w)
{
	int i,j;
	if ((i = LocateVex(G, v)) < 0)return ERROR;//判断顶点是否存在
	if ((j = LocateVex(G, v1)) < 0)return ERROR;
	if (i == j)return ERROR;
	G.arcs[i][j] = G.arcs[j][i] = w;//在邻接矩阵中增加边
	G.arcnum++;
	return OK;
}
//删除一个顶点
Status DeleteVex(AMGraph &G, char v[])
{
	int n,i; 
	if ((n=LocateVex(G,v))<0)//判断删除顶点是否存在
		return ERROR;
	for (i = n; i < G.vexnum; i++)//将该顶点删除,利用顺序表的前移覆盖删除
	{
		strcpy(G.vexs[i ].name, G.vexs[i+1].name);
		strcpy(G.vexs[i ].info, G.vexs[i+1].info);
	}	
	for (int k = 0; k < G.vexnum; k++)//将与顶点相关的路径也删除
		G.arcs[n][k] = G.arcs[k][n] = MaxInt;
	G.vexnum--;
	return OK;
}
//删除一条边
Status DeleteArc(AMGraph &G, char v[], char v1[])
{
	int i, j;
	if ((i = LocateVex(G, v)) < 0)return ERROR;//判断边的两端是否存在
	if ((j = LocateVex(G, v1)) < 0)return ERROR;
	G.arcs[i][j] = G.arcs[j][i] = MaxInt;//将路径删除
	G.arcnum--;
	return OK;
}
//菜单打印
Status print(AMGraph &G)
{
	printf("**************山河校园导游系统**************\n");
	int a; int v0, v3, v4; char v[200]; int Path[100]; int D[100];
	int i; char v1[200], v2[200]; 
	printf("请选择需要的服务:(1-8)\n");
	scanf("%d", &a);
	if (a == 1)
	{
		printf("本校的景点有:\n");
		for (i = 0; i < G.vexnum; ++i)
		printf("           %d.%s\n", i, G.vexs[i].name);
		printf("选择您要查询的景点序号:(0-%d)\n",G.vexnum-1);
		scanf("%d", &a);
		if (a >= G.vexnum || a < 0)printf("cannot find\n");
		else printf("%s  %s\n", G.vexs[a].name,G.vexs[a].info);
	}
	else if (a == 2)
	{
		printf("本校的景点有:\n");
		for (i = 0; i < G.vexnum; ++i)
			printf("           %d.%s\n", i, G.vexs[i].name);
		printf("请输入您的位置:\n");
		scanf("%s", v);
		v0 = LocateVex(G, v);
		ShortestPath_DIJ(G, v0, Path,D);
		printf("请输入您的目的地:\n");
		scanf("%s", v);
		v4 = v3 = LocateVex(G, v);
		printf("路径是:");
		SqStack S; int e;
		InitStack(S);
		while (v3 != v0)
		{
			Push(S, Path[v3]);
			v3 = Path[v3];
		}
		while (S.top != S.base)
		{
			Pop(S, e);
			printf("%s->", G.vexs[e].name);
		}
		printf("%s\n", G.vexs[v4].name);
		printf("最短距离是:%d\n", D[v4]);
	}
	else if (a == 3)
	{
		printf("请输入增加的景点名及相关信息:\n");
		scanf("%s %s", v1,v2);
		InsertVex(G, v1, v2);
	}
	else if (a == 4)
	{
		printf("修改景点名:\n");
		scanf("%s", v1);
		printf("需要修改的景点信息:\n");
		scanf("%s", v2);
		a=LocateVex(G, v1);
		strcpy(G.vexs[a].info,v2);
	}
	else if (a == 5)
	{
		printf("请输入路径的两端及距离:\n");
		scanf("%s %s %d", v1, v2,&a);
		InsertArc(G, v1, v2, a);
	}
	else if (a == 6)
	{
		printf("请输入删除的景点:\n");
		scanf("%s", v1);
		DeleteVex(G, v1);
	}
	else if (a == 7)
	{
		printf("请输入删除的路径的两端:\n");
		scanf("%s %s", v1,v2);
		DeleteArc(G, v1,v2);
	}
	else if (a == 8)
	{
		printf("**谢谢使用**\n");
		return 0;
	}
	else {
		printf("选择服务不存在\n");
		return 0;
	}
}

int main()
{
	printf("**************欢迎来到山河大学**************\n");
	printf("                1.查询景点信息                   \n");
	printf("                2.问路查询                   \n");
	printf("                3.增加一个景点及其相关信息                   \n");
	printf("                4.修改一个景点相关信息                   \n");
	printf("                5.增加一条新的路径                   \n");
	printf("                6.删除一个景点及其相关信息;                   \n");
	printf("                7.删除一条路径                   \n");
	printf("                8.退出                   \n");
	AMGraph G; CreatUDN(G);
	while ( print(G) != 0)
		;
}
  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值