基于c语言的校园导航应用程序开发
校园导航问题:设计青岛理工大学的平面图,至少包括10个以上的场所,每两个场所之间可以有不同的路,且路长也可能不同,找出从任意场所到达另一场所的最佳路径。即求最短路径
1、采用数据结构所学知识
2、利用弗洛伊德、迪杰斯特拉算法求出最短路径
3、系统的各个功能模块要求用函数的形式实现;
4、界面友好(良好的人机交互),程序添加必要的注释。
设计目的
随着高校的发展,校园面积不断扩大,校园内跨区域活动频繁,为了给校内师生和校外人士办公、教学、生活等方面带来更大的便利,以及面对校园信息化建设的全面推广和迅猛发展,本系统,将通过迪杰斯特拉和弗洛伊德算法,求出所需最短路径,进一步加强数字化校园建设。
设计内容和要求
图的最短路径问题是指从指定的某一点v开始,求得从该地点到图中其它各地点的最短路径。并且给出求得的最短路径的长度及途径的地点。设计学校的平面图,至少包括10个以上的场所,每两个场所间可以有不同的路,且路长也可能不同,找出从任意场所到达另一场所最短路径(即用迪杰斯特拉算法),以及从任意场所到达所有场所的最短路径(即用弗洛伊德算法)。 功能要求:
(1)将校园内各地点输出。
(2)查询各地点的详细信息。
求最短路径:输出给定地点之间的最短路径的长度及途经的地点。
一、校园导航系统模块图
(1)弗洛伊德算法流程图
(2)迪杰斯特拉算法流程图
(3)校区平面图
二、概要设计
本系统包含菜单(menu),输出地点编号(Number),查找(Query),弗洛伊德算法(floyd),求最短路径(shortesPath)。主程序为整个系统的入口处,菜单主要显示系统功能,显示信息主要实现地点信息,弗洛伊德算法主要实现两地点之间的最短路径,shortesPath函数主要实现输出两地点之间最短路径经过的地点与长度,查找地点信息主要实现显示某一地点的介绍。
系统首先通过主程序调用menu函数进行主菜单,根据用户的选择可分别进入:
1,查找地点信息
2,查找两地点之间的最短路径
3,退出系统
选择1项,显示青岛理工大学临沂校区的24个地点,包括地点编号。用户可进一步查询每个地点的介绍。
选择2项,会进入地点信息的界面,用户根据提示,输入地点信息里面提供的地点编号进行输入起始点和终点,输入正确后会显示两地点之间的最短路径,包括经过的地点,总路径长度。
选择3项,就会退出程序。
三、系统详细设计
(1)校园地点路径
place[1].name ,"南门"); place[2].name,"喷泉广场"); place[3].name,"实验楼区");
place[4].name,"教学楼区"); place[5].name,"办公楼"); place[6].name,"4号教学楼");
place[7].name,"3号教学楼"); place[8].name,"实训中心"); place[9].name,"图书馆");
place[10].name,"中心雕塑"); place[11].name,"小篮球场"); place[12].name,"操场");
place[13].name,"宿舍楼区"); place[14].name,"东苑餐厅"); place[15].name,"菜鸟驿站");
place[16].name,"大学生创业孵化基地");place[17].name,"1号宿舍楼");
place[18].name,"2号宿舍楼"); place[19].name,"篮球场"); place[20].name,"大学生中心");
place[20].name,"大学生活动中心");place[21].name,"杏园");place[22].name,"西苑餐厅");
place[23].name,"学海"); place[24].name,"西门");
构造校园网
校园无向网及路径
Graph Init_Graph(Graph *G) //构造校园网
{
int i,j;
G->vertexnum=24;
G->edgenum=44;
///初始化一下图 ,不存在的路径长度设为无穷大
for(i=0;i<=G->vertexnum;i++)
for(j=0;j<=G->vertexnum;j++)
G->edge[i][j]=INF;
具体输入图
for(i=1;i<=G->vertexnum;i++) //给每个地点标号
G->place[i].index=i;
以下输入地点编号和名称
for(i=0;i<=G->vertexnum;i++) //无向网的邻接矩阵关于对角线对称
for(j=0;j<=G->vertexnum;j++)
G->edge[j][i]=G->edge[i][j];
return *G;
}
(2)menu主菜单的实现
我们直接printf输出一个功能界面供用户选择。
(3)Query查找函数
如图,用户要查询图书馆的信息,系统显示。
如果输入的地点编号大于系统存储的最大值,那么返回地点编号不存在,如果用书输入的编号存在,则输出校园无向网中相对应的地点信息。
用户在功能菜单选择查看地点信息时,系统调用该函数。
(4)弗洛伊德算法
Floyd算法(Floyd-Warshall algorithm)又称为弗洛伊德算法、插点法,是解决给定的加权图中顶点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题。
算法过程:
1),从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。
2),对于每一对顶点u和v,看看是否存在一个顶点w使得从u到w再到v比已知的路径更短。如果是更新它。
把图用邻接矩阵G表示出来,如果从Vi到Vj有路可达,则G[i,j]=d,d表示该路的长度;否则G[i,j]=无穷大。定义一个矩阵D用来记录所插入点的信息,D[i,j]表示从Vi到Vj需要经过的点,初始化D[i,j]=j。把各个顶点插入图中,比较插点后的距离与原来的距离,G[i,j]=min(G[i,j],G[i,k]+G[k,j]),如果G[i,j]的值变小,则D[i,j]=k。在G中包含有两点之间最短路径的信息,而在D中则包含了最短通路径的信息。
比如,要寻找从V5到V1的路径。根据D,假如D(5,1)=3则说明从V5到V1经过V3,路径为{V5,V3,V1},如果D(5,3)=3,说明V5与V3直接相连,如果D(3,1)=1,说明V3与V1直接相连。
算法实现:
void floyd(Graph*G) //Floyd算法
{
int i,j,k;
//k为中间点
// i为起点
//j为终点
for(i=0;i<=G->vertexnum;i++)
for(j=0;j<=G->vertexnum;j++)
{
D[i][j]=G->edge[i][j];
if(i!=j&&G->edge[i][j]<INF)
path[i][j]=i;
else
path[i][j]=-1;
}
for(k=0;k<=G->vertexnum;k++)
for(i=0;i<=G->vertexnum;i++)
for(j=0;j<=G->vertexnum;j++)
if(D[i][k]+D[k][j]<D[i][j])
{
D[i][j]=D[i][k]+D[k][j];
path[i][j]=path[k][j];
}
}
(5)输出最短路径
void shortesPath_Floyd(Graph*G) //求最短路径
{
int i,j,p,m,k;
int b[100]; //将最短路径上所有经过的景点存在b数组里
floyd(G);
Number(G);
do
{
printf("请输起点编号:");
scanf("%d",&i);
printf("请输终点编号:");
scanf("%d",&j);
if(i==j)
printf("起点和终点一样,请重新输入\n");
else if(i>24||i<=0||j>24||j<=0)
printf("输入错误,请重新输入\n");
}while(i==j||i>24||i<=0||j>24||j<=0);
if(i!=j)
{
printf("起点:%s,终点:%s\n最短路径:",G->place[i].name,G->place[j].name);
p=path[i][j];
if(p==-1)
{
printf("empty\n");
}
else
{
m=0;
b[m++]=j;
while(p!=i)
{
b[m++]=p;
p=path[i][p];
}
b[m]=i;
for(k=m;k>0;k--)
printf("%s->",G->place[b[k]].name);
printf("%s,路程为%d米\n",G->place[b[0]].name,D[i][j]);
}
}
printf("\n\n请按任意键继续导航!\n\n");
getchar();
getchar();
}
如图所示,用户输入起点1为南门,13为宿舍区,可以看到系统输出的最短路径,
南门->喷泉广场->办公楼->3号教学楼->实训中心->图书馆->宿舍楼区,路程为480米
南门到东苑餐厅的最短路径:
南门->喷泉广场->办公楼->中心雕塑->东苑餐厅,路程为430米
总结
最短路径问题是图论研究中的一个经典算法问题。因此针对图最短路径问题先后提出了许多算法。各类算法的应用场景不尽相同。Dijkstra算法和Bellman-Ford算法用于解决单源最短路径,而Floyd算法可以解决多源最短路径。
Floyd算法在稠密图(邻接矩阵)和稀疏图(邻接表)中都可以使用。