校园导航系统,生成图,图之间最短路径问题(温习迪杰斯特拉算法,普利姆算法)

关于图,大家都觉特非常头疼,当你仔细看这个算法,细细品味,只觉得它是小菜一碟,希望给你带来帮助

#include "stdio.h"
#define  Infinity 1000
#define  MaxVertexNum 7
#define  MAX 20
#include "stdlib.h"
#include "string.h"
typedef struct arcell//边的信息 
{
int adj;//权值


}arcell,adjmatrix[MaxVertexNum][MaxVertexNum];
typedef struct vexsinfo//顶点信息 
{
int position;//景点的编号
char name[32];//景点名
char introduction[56];//景点的介绍
}vexsinfo;
typedef struct mgraph//使用邻接矩阵实现图的存储
{
vexsinfo vexs[MaxVertexNum];//数组顶点向量,存顶点信息
adjmatrix arcs;//邻接矩阵
int vexnum,arcnum;//顶点数和边数
}mgraph;




int visit[7];//标识dingdian是否访问过
int d[7];//用于存放权值或存储路径顶点编号
mgraph campus;//南阳理工学院校园
mgraph c;






mgraph initgraph()
{
int i=0,j=0;
c.vexnum=5;//顶点是5个
c.arcnum=7;//边 是6条
for(i=0;i<c.vexnum;i++)//设置顶点编号
c.vexs[i].position=i;
strcpy(c.vexs[0].name,"南阳理工学院大门");
strcpy(c.vexs[0].introduction,"长江路80号");
strcpy(c.vexs[1].name,"南阳理工学院图书馆");
strcpy(c.vexs[1].introduction,"进入学校门口直走50米");
strcpy(c.vexs[2].name,"梦西湖");
strcpy(c.vexs[2].introduction,"建立于2012年,里面有湖和亭子");
strcpy(c.vexs[3].name,"15号宿舍楼");
strcpy(c.vexs[3].introduction,"校车终点站,高7层");
strcpy(c.vexs[4].name,"南苑餐厅");
strcpy(c.vexs[4].introduction,"高两层,饭食可口");
for(i=0;i<c.vexnum;i++)
for(j=0;j<c.vexnum;j++)
c.arcs[i][j].adj=Infinity;//先初始化图的邻接矩阵
c.arcs[0][1].adj=50;c.arcs[0][4].adj=450;
c.arcs[1][2].adj=150;c.arcs[1][3].adj=180;c.arcs[1][4].adj=200;
c.arcs[2][3].adj=150;
c.arcs[3][4].adj=50;
for(i=0;i<c.vexnum;i++)
for(j=0;j<c.vexnum;j++)//邻接矩阵是对称矩阵。对称赋值


c.arcs[i][j].adj=c.arcs[j][i].adj;
return c;                    
}
void jingdianjieshao(mgraph c)
{
int i;
printf("编号\t景点名称\t\t景点简介\t\t\n");
printf("______________________________________________\n");
for(i=0;i<c.vexnum;i++)
printf("%-10d%-25s%-80s\n",c.vexs[i].position,c.vexs[i].name,c.vexs[i].introduction);
initgraph(campus);


printf("______________________________________________\n\n\n");
}






void allpath(mgraph c)//查看景点间的路线
{
//求从顶点v0到其余顶点的最短路径p[]及带权长度d[v](最短路径的距离)
//p[][]数组用于存放两顶点间是否有通路标识,如果p[v][w]=1,则w是从v0到v的最短路径上的顶点
//visited[数组用于设置访问标志
int v,w,i,min,t=0,x,v0;//v0为起始景点的编号
int visited[6],d[6],p[6][6];
printf("\n请输入一个起始景点的编号:");
scanf("%d",&v0);
printf("\n\n");
while(v0<0 ||v0>c.vexnum)
{
printf("\n您输入的景点不存在\n");
printf("请重新输入:");
scanf("%d",&v0);
}
for(v=0;v<c.vexnum;v++)
{
visited[v]=0;//初始化各个景点的访问标识
d[v]=c.arcs[v0][v].adj;//v0到各顶点v的权值赋给d[v],arcs是临界矩阵存两景点间的信息
for(w=0;w<c.vexnum;w++)
p[v][w]=0;//初始化数组,各顶点之间的路径全部设置为空
if(d[v]<Infinity)//v0到v有边相连,修改p[v][w]的值为1
{
p[v][v0]=1;
p[v][v]=1;//各顶点到自己要联通
}
}
d[v0]=0;//自己到自己的权值设置为0
visited[v0]=1;
for(i=1;i<c.vexnum;i++)//对其余c.vexnum-1个顶点w,一次求v到w的最短路径
{
min=Infinity;
for(w=0;w<c.vexnum;w++)
if(!visited[w])
if(d[w]<min)
{
v=w;min=d[w];
}
visited[v]=1;
for(w=0;w<c.vexnum;w++)
if(!visited[w]&&(min+c.arcs[v][w].adj<d[w]))//v到 w有边相连
{
d[w]=min+c.arcs[v][w].adj;//修改v0到w的权值d[w]
for(x=0;x<c.vexnum;x++)//所有v0到v的最短路径都是v0到w的最短路径上的顶点
p[w][x]=p[v][x];
p[w][w]=1;
}
}
for(v=0;v<c.vexnum;v++)//输出v0到其他景点v的最短路径
{
if(v!=v0)
printf("%s",c.vexs[v0].name);//输出景点v0的名称
for(w=0;w<c.vexnum;w++)//对图中每个顶点w,试探w是否是v0到v的最短路径上的顶点
{
if(p[v][w] &&w!=v0 && w!=v)//如果w是且不等于v0,则输出该景点
printf("---->%s",c.vexs[v].name);
}
printf("---->%s",c.vexs[v].name);
printf("\n总路线长为%d米:\n\n",d[v]);
}

}






void shotpath_Floyd(mgraph c)//使用费罗伊德算法实现最短路径
{//求各对顶点v和w间的最短路径p[][]及其带权长度d[v][w],若p[v][w][u]==1,则u是v到w的当前求得的最短路径上的顶点
int i,j,k,v,u,w,d[7][7],p[7][7][7];
for(v=0;v<c.vexnum;v++)//初始化各对顶点v,w之间的起始距离d[v][w]及路径p[v][w][]数组
{                               
for(w=0;w<c.vexnum;w++)
{
d[v][w]=c.arcs[v][w].adj;//d[v][w]中存放v至w间初始权值
for(u=0;u<c.vexnum;u++)//初始化p[v][w][]数组,第三分量全部清0
p[v][w][u]=0;
if(d[v][w]<Infinity)//如果v到w有边相连
{
p[v][w][v]=1;//v是v至w最短路径的顶点
p[v][w][w]=1;//w是v至w最短路径的顶点
}
}
}
for(u=0;u<c.vexnum;u++)//求v到w的最短路径及距离
{
//对任意顶点u,试探其是否为v到w最短路jing上的顶点
for(v=0;v<c.vexnum;v++)
for(w=0;w<c.vexnum;w++)
if(d[v][u]+d[u][w]<d[v][w])//从v经u到w的一条路径更短
{
d[v][w]=d[v][u]+d[u][w];//修改v到w的最短路径长度
for(i=0;i<c.vexnum;i++)//修改v到w的最短路径数组
p[v][w][i]=p[v][u][i]||p[u][w][i];//如果i是v到u的最短路径上的顶点,或i是u到w的最短路径上的顶点
}
}
printf("\n请输入出发点和目的地编号:");
scanf("%d%d",&k,&j);printf("\n\n");
while(k<0|| k>c.vexnum || j<0 || j>c.vexnum)
{
printf("\n您输入的景点编号不存在!");
printf("\n请重新输入出发点和目的地编号:");      
scanf("%d%d",&k,&j);printf("\n\n");
}
printf("%s",c.vexs[k].name);//输出出发点名称
for(u=0;u<c.vexnum;u++)
if(p[k][j][u] && k!=u &&j!=u)//输出最短路径上中间景点名称
printf("%s",c.vexs[k].name);//输出出发点名称
printf("--->%s",c.vexs[u].name);
printf("--->%s",c.vexs[j].name);//输出目的地的名称
printf("\n\n\n总长为%d米\n\n\n",d[k][j]);
}


void main()
{
int yourchoice;
 int flag=0;
 char w;
campus=initgraph();
printf("\t****************欢迎使用校园导游系统***************\t\t\n\n");
printf("\t                欢迎来到南阳理工学院校园!             \n\n");
printf("\t        1.学校景点介绍       2.查看两景点之间的游览路线           \n\n");
printf("\t        3.两景点间的最短路径 4.退出                   \n\n");
printf("\t***************************************************\t\t\n");
printf("请输入您的选择:");
scanf("%d",&yourchoice);
while(!(yourchoice==1||yourchoice==2||yourchoice==3||yourchoice==4))
{
printf("输入选择不正确,请重新输入");
scanf("%d",&yourchoice);
}
switch(yourchoice)
{
case 1:system("cls");jingdianjieshao(campus);break;
case 2:system("cls");allpath(campus);break;//查看景点间的路线
case 3:system("cls");shotpath_Floyd(campus);break;
case 4:system("cls");exit(1);break;
default:break;
}
printf("是否继续?(y/n):");
scanf("%d",&yourchoice);
do
{scanf("%c",&w);
printf("\n");
if(w!='y'&&w!='n')
printf("指令错误,请重新输入\n"); 
else
flag=1;
}while(flag==0);
if(w=='y')
{ printf("\t****************欢迎使用校园导游系统***************\t\t\n\n");
printf("\t                欢迎来到南阳理工学院校园!             \n\n");
printf("\t        1.学校景点介绍       2.查看两景点之间的游览路线           \n\n");
printf("\t        3.两景点间的最短路径 4.退出                   \n\n");
printf("\t***************************************************\t\t\n");
printf("请输入您的选择:");
scanf("%d",&yourchoice);
switch(yourchoice)
{
case 1:system("cls");jingdianjieshao(campus);break;
case 2:system("cls");allpath(campus);break;
case 3:system("cls");shotpath_Floyd(campus);break;
case 4:system("cls");exit(1);break;
default:break;
}
}while(w=='y');
}




功能图

                                                       

0:南阳理工学院北门,1:图书馆,2:梦西湖,3代表15号宿舍楼,4:南苑餐厅


需求分析描述

1.设计学校的校园平面图,选取若干个有代表性的经典抽象成一个无向网,以图中顶点表示校内各景点,边上的权值表示校内两景点之间的距离

2.存放景点代号、名称、简介信息供用户查询

3.为来访游客提供图中任意景点间相关的信息供用户查看

4.为来访游客提供图中任意景点间的最短路径

5.用户退出校园导游系统

 

系统结构设计、

1.功能图见压缩包

2.主界面设计

为了实现校园导游系统各功能的管理,首先设计一个含有多个菜单项的主控菜单子程序以链接系统的各项子功能,方便用户用户使用

3.存储结构设计

采用图结构类型(mgraph)存储抽象校园图的信息,其中,各景点间的邻接关系用图的邻接矩阵(adjmatrix)存储,景点信息用结构数组(vexs

)存储,其中每个数组元素是一个结构变量,包含景点编号、景点名称及景点介绍三个变量;图的顶点个数及边的个数由分量vexnumarcnum

示,它们是整形数据,此外,本系统还设置了三个全局变量:visit[]数组用于存储顶点是否被访问的标志,d[]数组用于存放边上的权值或存储

查找路径的编号;campus是一个图结构的全局变量

4.系统功能设计

1)学校景点介绍:选取南阳理工学院的5个景点:南阳理工大门,图书馆,梦西湖,15号宿舍楼和南苑餐厅。先对图进行初始化,初始化由函

initpraph()实现,依据读入的图的顶点个数和边的个数,分别初始化图结构中图的顶点向量数组和图的邻接矩阵,学校景点介绍由函数

jiandianjieshao()实现,用户选择该功能,系统即能输出学校全部景点的信息,包括景点编号、景点名称和景点简介

2)产看游览路线(提供图中任意景点间相关的信息供用户查看)

查看游览路线由函数allpath()实现,该功能采用迪杰斯特拉算法实现。用户使用该功能,系统根据用户输入的起始景点编号,求从该景点到其

他路径的最短路径路线和距离

3)查询景点间的最短路径

查询最短路径由函数shortpath_floyd()实现,该功能采用费罗伊德算法实现,当用户选用该功能,系统根据用户输入的起始景点编号和目的地编

号,查询任意两个景点之间的最短路径路线和距离

4)退出

退出校园导游系统,由exit0)函数实现

总结和体会

本导游图系统的功能设计比较简单,有一些更完美的设计没有实现,此导游图系统还有一定的局限性,如果存在只有一条通路的景点,导游图将

无法求得最佳旅游路径。通过这次的课程设计,通过图书馆借书和向学长们的请教,让我对数据结构中定义无向图和创建无向图的理解更加深刻

,不断提升认识,提高编程技巧,借以不断地提高程序设计水平,了解数据结构在编写比较复杂的程序的重要作用;理解了迪杰斯特拉算法和费

罗伊德的原理,但对于其算法的程序编写还是不太明白;学会了在编程序时如何查找错误,如何改错误等等, 总体来说,这次自己做得并不好,

没有掌握知识,对数据结构和C语言了解不透彻,设计的程序比较简单,功能不是很完整化,基本上完成了老师的要求,但还是存在一些问题主要

是对课本上的知识了解不够熟悉,浪费了大量时间去熟悉课本。对知识太过死板,不会灵活利用。所以,我决定以后通过图书馆更努力的学习数

据结构知识。

 

 

 

 

 

 

 

 

 


posted @ 2013-10-12 08:49  ZhangAihua  阅读(2534)  评论(0编辑  收藏  举报