数据结构课程设计之校园导航系统.docx
《数据结构课程设计之校园导航系统.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计之校园导航系统.docx(28页珍藏版)》请在冰豆网上搜索。
数据结构课程设计之校园导航系统
##大学
数据结构课程设计报告
题目:
校园导航系统
院(系):
计算机工程学院
学生姓名:
班级:
学号:
起迄日期:
2011.6.19--6.30
指导教师:
指导教师评语:
成绩:
签名:
年月日
20XX—20XX年度第2学期
一、需求分析
1.问题描述:
从理工大学的平面图中选取10个有代表性的景点,抽象成一个无向带权图。
以图中顶点表示景点,边上的权值表示两地之间的距离,求取任意两点间最短路径。
2.基本功能
本程序主要实现的功能是为用户提供路径咨询。
根据用户指定的始点和终点输出相应路径(用到output()函数),或者根据用户指定的景点输出景点的信息(用到search()函数)。
3.输入输出
本程序主要输入输出信息是景点编号和景点名称,以字符串的形式输入输出。
二、概要设计
1.设计思路:
本程序是校园导航系统,即求两点间的最短路径。
其主要算法是迪杰斯特拉算法,在此基础上再加上菜单函数输出函数造图函数查找函数即可。
2.数据结构设计:
抽象数据类型图的定义如下:
ADTGraph{
数据对象V:
V是具有相同特性的数据元素的集合,称为顶点集。
数据关系R:
R={VR}
VR={(v,w)|v,wV,(v,w)表示v和w之间存在路径}
基本操作p:
CreatGraph(&G,V,VR)
初始条件:
V是图的顶点集,VR是图中边的集合。
操作结构:
按V和VR的定义构造图G。
DestroyGraph(&G)
初始条件:
图G存在。
操作结果:
销毁图G。
LocateVex(G,u)
初始条件:
图G存在,u和G中顶点有相同特征。
操作结果:
若G中存在顶点u,则返回该顶点在图中位置;否则返回其他信息。
GetVex(G,v)
初始条件:
图G存在,v是G中某个顶点。
操作结果:
返回v的信息。
FirstEdge(G,v)
初始条件:
图G存在,v是G中某个顶点。
操作结果:
返回依附于v的第一条边。
若该顶点在G中没有邻接点,则返回“空”。
NextEdge(G,v,w)
初始条件:
图G存在,v是G中某个顶点,w是v的邻接顶点。
操作结果:
返回依附于v的(相对于w的)下一条边。
若不存在,则返回“空”。
InsertVex(&G,v)
初始条件:
图G存在,v和图中顶点有相同特征。
操作结果:
在图G中增添新顶点v。
DeleteVex(&G,v)
初始条件:
图G存在,v是G中某个顶点。
操作结果:
删除G中顶点v及其相关的边。
GetShortestPath(G,st,nd,&Path)
初始条件:
图G存在,st和nd是G中的两个顶点。
操作结果:
若st和nd之间存在路径,则以Path返回两点之间一条最短路径,否则返回其他信息。
3.软件结构设计:
voidCreatUDN(intv,inta)造图函数
voidnarrate()说明函数
voidShortestPath(intnum)最短路径函数
voidoutput(intsight1,intsight2)输出函数
voidsearch()查询函数
charMenu()主菜单
charSearchMenu()查询子菜单函数
主程序模块
带权无向图模块
三、详细设计
1.边顶点和图类型
#defineMax20000
#defineNUM10
typedefstructArcCell{
intadj;/*相邻接的景点之间的路程*/
}ArcCell;/*定义边的类型*/
typedefstructVertexType{
intnumber;
char*sight;
char*info;
}VertexType;/*定义顶点的类型*/
typedefstructMGraph{
VertexTypevex[NUM];/*图中的顶点,即为景点*/
ArcCellarcs[NUM][NUM];/*图中的边,即为景点间的距离*/
intvexnum,arcnum;
}MGraph;/*定义图的类型*/
2.voidmain()/*主函数*/
{
intv0,v1;
charck;
CreateUDN(NUM,11);
do
{
ck=Menu();
switch(ck)
{
case'1':
system("cls");
narrate();/*输出景点列表*/
printf("\n\n\t\t\t请选择起点景点(0~9):
");
scanf("%d",&v0);
printf("\t\t\t请选择终点景点(0~9):
");
scanf("%d",&v1);
ShortestPath(v0);/*计算两个景点之间的最短路径*/
output(v0,v1);/*输出结果*/
printf("\n\n\t\t\t\t请按任意键继续...\n");
getchar();
getchar();
break;
case'2':
search();
break;
};
}while(ck!
='e');
}
charMenu()/*主菜单*/
{
charc;
intflag;
do{
flag=1;
system("cls");
narrate();/*输出景点列表*/
printf("\n\t\t\t┏━━━━━━━━━━━━━━━┑\n");
printf("\t\t\t┃┃\n");
printf("\t\t\t┃1、查询景点路径┃\n");
printf("\t\t\t┃2、查询景点信息┃\n");
printf("\t\t\t┃e、退出┃\n");
printf("\t\t\t┃┃\n");
printf("\t\t\t┗━━━━━━━━━━━━━━━┛\n");
printf("\t\t\t\t请输入您的选择:
");
scanf("%c",&c);
if(c=='1'||c=='2'||c=='e')
flag=0;
}while(flag);
returnc;
}
charSearchMenu()/*查询子菜单*/
{
charc;
intflag;
do{
flag=1;
system("cls");
narrate();/*输出景点列表*/
printf("\n\t\t\t┏━━━━━━━━━━━━━━━┑\n");
printf("\t\t\t┃┃\n");
printf("\t\t\t┃1、按照景点编号查询┃\n");
printf("\t\t\t┃2、按照景点名称查询┃\n");
printf("\t\t\t┃e、返回┃\n");
printf("\t\t\t┃┃\n");
printf("\t\t\t┗━━━━━━━━━━━━━━━┛\n");
printf("\t\t\t\t请输入您的选择:
");
scanf("%c",&c);
if(c=='1'||c=='2'||c=='e')
flag=0;
}while(flag);
returnc;
}
voidsearch()/*查询景点信息*/
{
intnum;
inti;
charc;
charname[20];
do
{
system("cls");
c=SearchMenu();
switch(c)
{
case'1':
system("cls");
narrate();/*输出景点列表*/
printf("\n\n\t\t请输入您要查找的景点编号:
");
scanf("%d",&num);
for(i=0;i{
if(num==G.vex[i].number)
{
printf("\n\n\t\t\t您要查找景点信息如下:
");
printf("\n\n\t\t\t%-25s\n\n",G.vex[i].info);
printf("\n\t\t\t按任意键返回...");
getchar();
getchar();
break;
}
}
if(i==NUM)
{
printf("\n\n\t\t\t没有找到!
");
printf("\n\n\t\t\t按任意键返回...");
getchar();
getchar();
}
break;
case'2':
system("cls");
narrate();
printf("\n\n\t\t请输入您要查找的景点名称:
");
scanf("%s",name);
for(i=0;i{
if(!
strcmp(name,G.vex[i].sight))
{
printf("\n\n\t\t\t您要查找景点信息如下:
");
printf("\n\n\t\t\t%-25s\n\n",G.vex[i].info);
printf("\n\t\t\t按任意键返回...");
getchar();
getchar();
break;
}
}
if(i==NUM)
{
printf("\n\n\t\t\t没有找到!
");
printf("\n\n\t\t\t按任意键返回...");
getchar();
getchar();
}
break;
}
}while(c!
='e');
}
voidCreateUDN(intv,inta)/*造图函数*/
{
inti,j;
G.vexnum=v;/*初始化结构中的景点数和边数*/
G.arcnum=a;
for(i=0;iG.vex[i].number=i;/*初始化每一个景点的编号*/
/*初始化没一个景点名及其景点描述*/
G.vex[0].sight="实验楼";
G.vex[0].info="学生及科研人员做实验";
G.vex[1].sight="科学会堂";
G.vex[1].info="学生业余活动,举办各种晚会。
";
G.vex[2].sight="7号楼";
G.vex[2].info="男生宿舍楼";
G.vex[3].sight="3号楼";
G.vex[3].info="女生宿舍楼";
G.vex[4].sight="澡堂";
G.vex[4].info="供学生洗澡的地方";
G.vex[5].sight="操场";
G.vex[5].info="学生锻炼健身的场所";
G.vex[6].sight="B区教学楼";
G.vex[6].info="教室,学生上课自习的地方";
G.vex[7].sight="图书馆";
G.vex[7].info="藏有丰富的书籍,供学生和老师参考";
G.vex[8].sight="A区教学楼";
G.vex[8].info="老师办公室";
G.vex[9].sight="餐厅";
G.vex[9].info="师生及工作人员吃饭的地方";
/*这里把所有的边假定为20000,含义是这两个景点之间是不可到达*/
for(i=0;ifor(j=0;jG.arcs[i][j].adj=Max;
/*下边是可直接到达的景点间的距离,由于两个景点间距离是互相的,
所以要对图中对称的边同时赋值。
*/
G.arcs[0][1].adj=G.arcs[1][0].adj=6;
G.arcs[0][2].adj=G.arcs[2][0].adj=4;
G.arcs[0][3].adj=G.arcs[3][0].adj=5;
G.arcs[1][4].adj=G.arcs[4][1].adj=1;
G.arcs[2][4].adj=G.arcs[4][2].adj=1;
G.arcs[3][5].adj=G.arcs[5][3].adj=2;
G.arcs[5][7].adj=G.arcs[7][5].adj=4;
G.arcs[4][6].adj=G.arcs[6][4].adj=9;
G.arcs[4][7].adj=G.arcs[7][4].adj=7;
G.arcs[6][8].adj=G.arcs[8][6].adj=2;
G.arcs[7][8].adj=G.arcs[8][7].adj=4;
G.arcs[8][9].adj=G.arcs[9][8].adj=4;
}
voidnarrate()/*说明函数*/
{
inti=0;
printf("\n\t\t\t*****欢迎使用理工大校园导游程序*****\n");
printf("\t________________________________\n");
printf("\t\t景点名称\t\t\n");
printf("\t________________________________\n");
for(i=0;i{
printf("\t%c(%2d)%-10s\t\t\n",3,i,G.vex[i].sight);/*输出景点列表*/
}
printf("\t________________________________\n");
}
voidShortestPath(intnum)/*迪杰斯特拉算法最短路径函数num为入口点的编号*/
{
intv,w,i,t;/*i、w和v为计数变量*/
intfinal[NUM];/*若P[v][w]为1,则w是从顶点num到v当前求得最短路径上的顶点*/
intmin;//final[v]为1,当且仅当v属于s,即已经求得从num到v的最短路径
for(v=0;v{
final[v]=0;/*假设从顶点num到顶点v没有最短路径*/
D[v]=G.arcs[num][v].adj;/*将与之相关的权值放入D中存放*/
for(w=0;wP[v][w]=0;/*设置为空路径*/
if(D[v]<20000)/*存在路径*/
{
P[v][num]=1;/*存在标志置为一*/
P[v][v]=1;/*自身到自身*/
}
}
D[num]=0;
final[num]=1;/*初始化,num顶点属于S集合*/
/*开始主循环,每一次求得num到某个顶点的最短路径,并将其加入到S集合*/
for(i=0;i{
min=Max;/*当前所知离顶点num的最近距离*/
for(w=0;wif(!
final[w])/*w顶点在v-s中*/
if(D[w]{
v=w;
min=D[w];
}
final[v]=1;/*离num顶点更近的v加入到s集合*/
for(w=0;wif(!
final[w]&&((min+G.arcs[v][w].adj){
D[w]=min+G.arcs[v][w].adj;
for(t=0;tP[w][t]=P[v][t];
P[w][w]=1;
}
}
}
voidoutput(intsight1,intsight2)/*输出函数*/
{
inta,b,c,d,q=0;
a=sight2;/*将景点二赋值给a*/
if(a!
=sight1)/*如果景点二不和景点一输入重合,则进行...*/
{
printf("\n\t从%s到%s的最短路径是",G.vex[sight1].sight,G.vex[sight2].sight);/*输出提示信息*/
printf("\t(最短距离为%dm.)\n\n\t",D[a]);/*输出sight1到sight2的最短路径长度,存放在D[]数组中*/
printf("\t%s",G.vex[sight1].sight);/*输出景点一的名称*/
d=sight1;/*将景点一的编号赋值给d*/
for(c=0;c{
gate:
;/*标号,可以作为goto语句跳转的位置*/
P[a][sight1]=0;
for(b=0;b{
if(G.arcs[d][b].adj<20000&&P[a][b])/*如果景点一和它的一个临界点之间存在路径且最短路径*/
{
printf("-->%s",G.vex[b].sight);/*输出此节点的名称*/
q=q+1;/*计数变量加一,满8控制输出时的换行*/
P[a][b]=0;
d=b;/*将b作为出发点进行下一次循环输出,如此反复*/
if(q%9==0)printf("\n");
gotogate;
}
}
}
}
}
3.
输出函数算法流程图
4.函数调用图:
Main
SearchCreateUDNNarrateShortestPathOutputMenu
SearchMenu
四、调试分析
1.本程序实现了查询校园中任意两景点的最短路径的功能,同时也显示了两景点最短路径的实际距离。
也可以查询任意景点的信息,包括按景点编号查询和按景点名称查询。
2.考虑道路网多是稀疏网,故采用邻接多重表作存储结构,其空间复杂度为O(e),此时的时间复杂度也为O(e)。
构建邻接多重表的时间复杂度为O(n+e),输出路径的时间复杂度为O(n)。
由此,本导游程序的时间复杂度为O(n+e)。
3.在创建造图函数时,由于两个景点的距离是相互的,所以要对图中对称的边要同时赋值,开始时没有注意到这一点,导致程序总是有错误。
4.本程序除了迪杰斯特拉算法外,基本全是用最简单的c语言编写的,行数比较多。
有些地方可以用指针链表代替,这样可以缩短篇幅,更加简单易懂。
5.可扩展的功能有求校园图的关节点,提供校园图中多个景点的最佳访问路线查询,即求途经这多个景点的最佳路径。
五、测试结果
1.进入程序操作页面后操作命令符为1,
起点景点:
7号楼
(2);终点景点:
操场(5);
最短路径:
7号楼---实验楼---3号楼---操场
最短路径长度:
11m
起点景点:
实验楼(0);终点景点:
B区教学楼(6);
最短路径:
实验楼---7号楼---澡堂---B区教学楼
最短路径长度:
14m
2.操作命令符为2,
景点编号查询:
7
景点信息:
藏有丰富图书,供学生及老师参考
景点名称查询:
科学会堂
景点信息:
学生业余活动,举办各种晚会
六、用户手册
1.进入演示程序后随即显示如下的文本方式的用户界面:
2.进入“查询景点路径
(1)”的命令后,即提示输入起始点和终点的编号,输入编号后即显示两点之间的一条最短路径及距离:
3.进入“查询景点信息
(2)”的命令后,即提示按景点编号查询
(1)和按景点名称查询
(2):
输入1后显示如下:
输入2后显示如下:
7、体会与自我评价
由于疏忽,我是在开始上机做实验的前一天匆忙选的设计课题,那时课题基本已被选完了,就剩下几个比较难的课题了,我就随便选择了校园导航系统。
说实在的,开始的时候对校园导航系统一点也不了解,根本不知道校园导航系统要用到什么知识。
就这样,我迎来了为期两个星期的数据结构课程设计实验。
在接下来的时间里,我就在规定的时间里去学校的实验室做实验,在其余的时间里到网上查询一些关于校园导航系统的一些资料,了解编写校园导航系统涉及的核心知识。
通过查询我知道了校园导航系统的关键是最短路径问题,在教材中用算法---迪杰斯特拉求最短路径问题。
花了几天的时间到教室自习,先是弄懂啥叫迪杰斯特拉算法,该算法是怎样实现的,然后一直在研究该算法在用c语言是怎样表达的。
其实迪杰斯特拉算法的主要思想很容易懂,可是它的c语言描述很难理解,不过最终我还是依据课本上的c语言算法描述改写成了适合自己课题的程序代码。
校园导航系统程序的核心即已经编出来,其余的主函数菜单函数等就很简单了。
整个程序很快就大体编写完成了,不过在运行的时候还是有几个错误。
自己看了很长时间,改了又改,终于在同学的帮助下完成了整个程序。
曲折的是,在最终的答辩时,我还是答了两次。
第一次有点紧张,开始还挺顺利,可是突然老师提了一个有关图的存储位置问题,我傻眼了,没回答上来,第一次答辩就这样失败了。
后来我回去又仔细的看了几遍自己的程序,最终通过了下次的答辩。
为期两周的数据结构课程设计就这样结束了。
通过这次课程设计,我学会了很多。
一个大型的程序是需要丰富的编程知识和团队合作。
要想以后能够独立自主的开发新的软件,现在就必须多多涉猎各种编程知识,为以后打下坚实的基础。
源代码
#include"string.h"
#include"stdio.h"
#include"malloc.h"
#include"stdlib.h"
#defineMax20000
#defineNUM10
typedefstructArcCell{
intadj;/*相邻接的景点之间的路程*/
}ArcCell;/*定义边的类型*/
typedefstructVertexType{
intnumber;
char*sight;
char*info;
}VertexType;/*定义顶点的类型*/
typedefstructMGraph{
VertexTypevex[NUM];/*图中的顶点,即为景点*/
ArcCellarcs[NUM][NUM];/*图中的边,即为景点间的距离*/
intvexnum,arcnum;
}MGraph;/*定义图的类型*/
MGraphG;/*把图定义为全局变量*/
intP[NUM][NUM];/**/
longintD[NUM];/*辅助变量存储最短路径长度