OUC_数据结构与算法_第七章实验:校园导游咨询

实验目的:掌握图的存储方法和最短路经算法。

实验内容:设计一个校园导游程序,为来访客人提供各种信息查询服务。测试数据根据实际情况指定。提示:一般情况下,校园的道路是双向通行的,可设校园平面图是一个无向图。顶点和边均含有相关信息。

实验要求:

1、设计西海岸校园平面图,所含Point of Interest(PoI)不少于10个。以图中顶点表示校内各PoI,存放PoI名称、代号、简介等信息;以边表示路径,存放路径长度等相关信息。(4分)

2、为来访客人提供图中任意PoI相关信息的查询。(2分)

3、为来访客人提供图中任意PoI的纹路查询,即查询任意两个PoI之间的一条最短的简单路径。(4分)

C语言代码如下:

/*
实验题目:校园导游咨询
实验目的:掌握图的存储方法和最短路经算法。
实验内容:设计一个校园导游程序,为来访客人提供各种信息查询服务。
测试数据根据实际情况指定。
提示:一般情况下,校园的道路是双向通行的,可设校园平面图是一个无向图。
顶点和边均含有相关信息。
实验要求:
1、设计西海岸校园平面图,所含Point of Interest(PoI)不少于10个。
以图中顶点表示校内各PoI,存放PoI名称、代号、简介等信息;
以边表示路径,存放路径长度等相关信息。(4分)
2、为来访客人提供图中任意PoI相关信息的查询。(2分)
3、为来访客人提供图中任意PoI的纹路查询,
即查询任意两个PoI之间的一条最短的简单路径。(4分)
*/

/*测试用例
10 10
0 东海 海纳百川,取则行远。 
1 听海餐厅 人间有味是清欢。 
2 电子信息楼 谨防电信诈骗! 
3 学习综合体 非学无以广才,非志无以成学。 
4 计算机楼 计算万物,机敏过人。
5 大门 一夫当关,万夫莫开。 
6 海洋生物资源开发中心 连弩射海鱼,长鲸正崔嵬。
7 体育中心 发展体育运动,增强人民体质。 
8 医务室 救人一命,胜造七级浮屠。
9 望海餐厅 金樽清酒斗十千,玉盘珍羞直万钱。
0 1 800
1 2 100
1 5 200
2 3 50
3 4 50
5 7 100
6 7 100
6 8 100
7 9 100
8 9 100
*/ 


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define VertexMax 10 //最大顶点数为10
#define MaxInt 32767 //表示最大整数,表示 ∞ 

typedef struct
{
	char name[30];	//名称 
	int id;			//代号 
	char info[50];	//简介 
}PoI;//存放顶点PoI信息 

typedef struct
{
	PoI Vertex[VertexMax];				//存放顶点PoI元素的一维数组 
	int AdjMatrix[VertexMax][VertexMax];//存放边长度的邻接矩阵二维数组 
	int vexnum,arcnum;					//记录图的顶点数和边数  
}MGraph;//图=顶点+边 

//实验要求1、设计西海岸校园平面图,所含Point of Interest(PoI)不少于10个。
//以图中顶点表示校内各PoI,存放PoI名称、代号、简介等信息;
//以边表示路径,存放路径长度等相关信息。(4分)
void createG(MGraph *G) 
{
	int i,j;
	//1.输入顶点数和边数 
	printf("输入顶点个数和边数(中间用空格隔开):"); 
	scanf("%d %d",&G->vexnum,&G->arcnum);

	//2.输入顶点元素 
	printf("输入顶点元素PoI代号(0-9)、名称、简介(中间用空格隔开):\n");
	for(i=0;i<G->vexnum;i++)
	{
		scanf("%d",&G->Vertex[i].id);
		scanf(" %s",&G->Vertex[i].name);
		scanf(" %s",&G->Vertex[i].info);
	//输出测试 
	//		printf("input%d展示:id = %d,name = %s,info = %s\n",
	//		i,G->Vertex[i].id,G->Vertex[i].name,G->Vertex[i].info);
	} 
	
	//3.邻接矩阵元素初始化(对角线位置设为0,非对角线位置设为无穷) 
	for(i=0;i<G->vexnum;i++)
	{
		for(j=0;j<G->vexnum;j++)
		{
			G->AdjMatrix[i][j]=MaxInt;
		}
	}
	
	//4.构建邻接矩阵存储边信息 
	PoI v1,v2;
	int w;//v1->v2的权值 
	
	printf("输入路径(两个顶点的代号)及路径长度(中间用空格隔开):\n");
	for(i=0;i<G->arcnum;i++)
	{
		printf("输入第%d条路径信息:",i+1);
		scanf("%d %d %d",&v1.id,&v2.id,&w);
		//因为是无向图,所以邻接矩阵对称位置也要赋相同值 
		G->AdjMatrix[v1.id][v2.id]=G->AdjMatrix[v2.id][v1.id]=w;
	}
}

void display(MGraph G)
{
	int i,j;
	printf("全部PoI:\n\n");
	printf("\t代号\t名称\t\t\t简介\n");
	for(i=0;i<G.vexnum;i++)
	{
		printf("\t%d\t%-20s\t%-50s\n",
		G.Vertex[i].id,G.Vertex[i].name,G.Vertex[i].info);
	}
	printf("\n邻接矩阵:\n\n"); 
	printf("\t代号 ");
	for(i=0;i<G.vexnum;i++)
	{
		printf("\t(%d)",G.Vertex[i].id);
	}
	printf("\n");
	
	for(i=0;i<G.vexnum;i++)
	{
		printf("\t(%d)",G.Vertex[i].id);
		for(j=0;j<G.vexnum;j++)
		{
			if(G.AdjMatrix[i][j]==MaxInt)
			{
				printf("\t∞");
			}else
			{
				printf("\t%d",G.AdjMatrix[i][j]);
			}
		}
		printf("\n");
	} 
}

//实验要求2、为来访客人提供图中任意PoI相关信息的查询。(2分)
int search(MGraph G)
{
	printf("请输入PoI的代号或名称:"); 
	int i,id;
	char c[30];
	scanf("%s",c);
	if(c[0]>='0' && c[0]<='9')	//若字符数组首元素是数字则按id查找 
	{
		id = c[0]-'0';
		for(i=0;i<G.vexnum;i++)
		{
			if(id==G.Vertex[i].id)
			{
				printf("代号为 '%d' 的PoI信息:\n\n",id);
				printf("\t代号\t名称\t\t\t简介\n");
				printf("\t%d\t%-20s\t%-50s\n",
				G.Vertex[i].id,G.Vertex[i].name,G.Vertex[i].info);
				return i; 
			} 
		} 
	}else		//若字符数组首元素不是数字则按name字符数组查找 
	{
		for(i=0;i<G.vexnum;i++)
		{
			if(!strcmp(c,G.Vertex[i].name))
			{
				printf("名称为 '%s' 的PoI信息:\n\n",c);
				printf("\t代号\t名称\t\t\t简介\n");
				printf("\t%d\t%-20s\t%-50s\n",
				G.Vertex[i].id,G.Vertex[i].name,G.Vertex[i].info);
				return i; 
			} 
		} 
	}
	printf("查无此点!\n");
	return -1;
}



//输出最短路径 
void displayPath(int dist[],int path[],MGraph *G,PoI start,PoI end)
{
	int i,k;
	int temp[VertexMax];//临时数组 
	PoI target;//目标地点 
	int loc=0; 
	
	for(i=0;i<VertexMax;i++)
	{
		temp[i]=-1;
	}
	printf("迪杰斯特拉算法结果展示:\n\n");
	//打印dist数组 
	printf("\tdist[i]:\n\t");
	for(i=0;i<G->vexnum;i++)
	{
		printf("\t%d",i);	
	}
	printf("\n\t"); 
	  for(i=0;i<G->vexnum;i++)
    {
    	printf("\t%d",dist[i]);
	}
	printf("\n\n");
	//打印path数组 
	printf("\tpath[i]:\n\t");
	for(i=0;i<G->vexnum;i++)
	{
		printf("\t%d",i);
	}
	printf("\n\t"); 
	for(i=0;i<G->vexnum;i++)
    {
    	printf("\t%d",path[i]);
	}
    printf("\n\n"); 
    
	//输出最短路径 
	printf("最短路径:\n\n"); 
	loc=end.id;
	int j=0;		//j统计跳数 
	while(loc!=-1)
	{
		temp[j]=loc;
		loc=path[loc];
		j++;
	}
	printf("\t%s to %s: ",start.name,end.name);
	for(j=j-1;j>=0;j--)
	{
		printf("%s",G->Vertex[temp[j]].name);
		if(j!=0){
			printf("->");
		}
	}
	printf("(总路径长度:%d米)\n\n",dist[end.id]);
		
	for(k=0;k<20;k++)
	{
		temp[k]=-1;
	}
}

//找到最小的dist,用于迪杰斯特拉算法 
int FindMinDist(int dist[],int s[],int vexnum) 
{
	int i;
	int loc;
	int min=MaxInt+1;
	for(i=0;i<vexnum;i++)
	{
		if(s[i]==0)//只对s[i]=0的顶点进行查找 
		{
			if(dist[i]<min)
			{
				min=dist[i];
				loc=i;
			}
		}
	}
	return loc;//返回dist中最小元素的下标 
}

//实验要求3、为来访客人提供图中任意PoI的纹路查询,
//即查询任意两个PoI之间的一条最短的简单路径。(4分)
//采用了迪杰斯特拉算法 
void shortestPath(MGraph *G)
{
	PoI start,end;
	printf("请输入起点的代号或名称:"); 
	char c1[30],c2[30];
	scanf("%s",c1);
	//printf("c1 = %s\n",c1);
	//定位start 
	if(c1[0]>='0' && c1[0]<='9')
	{
		start.id = c1[0]-'0';
		for(int i=0;i<G->vexnum;i++)
		{
			if(start.id==G->Vertex[i].id)
			{
				for(int j=0;j<30;j++){
					start.name[j] = G->Vertex[i].name[j];
				}
				for(int j=0;j<50;j++){
					start.info[j] = G->Vertex[i].info[j];
				}
			} 
		} 
	}else{
		for(int i=0;i<G->vexnum;i++)
		{
			if(!strcmp(c1,G->Vertex[i].name))
			{
				start.id = G->Vertex[i].id;
				for(int j=0;j<30;j++){
					start.name[j] = G->Vertex[i].name[j];
				}
				for(int j=0;j<50;j++){
					start.info[j] = G->Vertex[i].info[j];
				}
			} 
		} 
	}
	printf("请输入终点的代号或名称:"); 
	scanf("%s",c2);
	//printf("c2 = %s\n",c2);
	//定位end
	if(c2[0]>='0' && c2[0]<='9')
	{
		end.id = c2[0]-'0';
		for(int i=0;i<G->vexnum;i++)
		{
			if(end.id==G->Vertex[i].id)
			{
				for(int j=0;j<30;j++){
					end.name[j] = G->Vertex[i].name[j];
				}
				for(int j=0;j<50;j++){
					end.info[j] = G->Vertex[i].info[j];
				}
				//printf("end.name = %s,end.info = %s\n",end.name,end.info);
				break;
			}
		} 
	}else{
		for(int i=0;i<G->vexnum;i++)
		{
			if(!strcmp(c2,G->Vertex[i].name))
			{
				end.id = G->Vertex[i].id;
				for(int j=0;j<30;j++){
					end.name[j] = G->Vertex[i].name[j];
				}
				for(int j=0;j<50;j++){
					end.info[j] = G->Vertex[i].info[j];
				}
				//printf("end.name = %s,end.info = %s\n",end.name,end.info);
				break; 
			} 
		} 
	}
	
	int i,j,num;
	int loc;
	int min;
	int dist[VertexMax];//存储最短路径长度数组 
	int path[VertexMax];//存储最短路径数组 
	int s[VertexMax];//代表集合S,用来区分是否被纳入路径 
	
	//1.初始化dist和path数组 
	loc=start.id;	//获取源点的下标位置 
	for(i=0;i<G->vexnum;i++)
	{
		dist[i]=G->AdjMatrix[loc][i];
		
		if(dist[i]!=MaxInt)
		{
			path[i]=loc;
		}
		else
		{
			path[i]=-1;
		}	  
	} 
    
    //2.初始化S数组
	//s数组:代表集合S,用1代表该元素属于集合S(已处理的顶点)
	//用0该元素不属于集合S(未处理的顶点)
    for(i=0;i<G->vexnum;i++)
	{
		s[i]=0;
	} 
	s[loc]=1;//代表起始点(源点)以处理完毕 
	num=1;
	
	//3.迪杰斯特拉算法 
	while(num<G->vexnum)
	{
		min=FindMinDist(dist,s,G->vexnum);//在dist数组中查找其对应s[i]=0,即未处理的最小值元素 
		s[min]=1;//将找到的最短边所对应的的顶点加入集合S
		
		for(i=0;i<G->vexnum;i++)//加入新的顶点后,更新dist和path数组 
		{
			if((s[i]==0)&&(dist[i]>dist[min]+G->AdjMatrix[min][i]))
			{
				dist[i]=dist[min]+G->AdjMatrix[min][i];
				path[i]=min;//min->i
			}
		}
	    num++;	
	} 
    displayPath(dist,path,G,start,end);//展示dist数组、path数组及最短路径 
} 

int main() 
{
	printf("--------------------校园导游程序--------------------\n");
	MGraph G;
	printf("录入数据:\n");
	createG(&G);
	printf("录入完成!\n");
	while(true){
		int choice = 0;
		printf("--------------------校园导游程序--------------------\n");
		printf("功能选择:0.退出程序  1.展示全部PoI和边  " 
		  "2.查询PoI信息  3.查询最短路径\n");
		printf("你的选择是:");
		scanf("%d",&choice);
		switch(choice){
			case 0:return 0;break;
			case 1:display(G);break;
			case 2:search(G);break;
			case 3:shortestPath(&G);break; 
		}
	}
	return 0;
}

        记录一下曾经的努力,欢迎大家讨论和借鉴! 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值