一.设计目的1.强化上机动手能力,在理论和实践的基础上进一步巩固《数据结构》课程学习的内容,掌握工程化软件设计的基本方法;2.掌握图的创建和应用;3.掌握迪杰斯特拉以及Prim等基本算法思想;4.掌握if语句及switch语句的运用方法及嵌套应用方法;5.掌握C语言主函数和被调用函数之间的参数传递方式,学会函数的调用过程和方法;6.掌握结构体类型变量的定义和使用;7.掌握指针变量和指向指针的指针变量的定义及使用,进一步了解指向结构体的指针变量的概念及使用方法;8.能够采用模块化思想调试程序;9.学会将知识应用于实际的方法,提高分析和解决问题的能力,增加综合能力;10.为后续各门计算机课程的学习打下坚实基础。二.设计内容用C语言编写了《西邮校园导游咨询系统》,通过使用循环、条件、数组、结构体、函数、指针、等相关C语言知识学习编写较大的程序,结合数据结构中的算法思想实现一个导游咨询系统基本的功能。三.概要设计1.功能模块图;退出界面西邮沿途风景,ATM机介绍新鲜资讯修改景点信息,新西邮两个景点间的最短距离输入出发点和目的地获取所有游览线路从某一景点出发的最短连通路线从一个景点到其他所有景点的最短距离查看景点信息浏览校园全景西邮校园导游咨询系统2.各个模块详细的功能描述。(1).浏览校园全景可让用户浏览校园平面全景图,图上信息包括景点名称,路径长度,风景位置,ATM机位置等,一目了然。(2).查看景点信息用户根据界面显示的校园景点信息表,输入要查询的景点名称,可以查看景点信息。(3).从一个景点到其他所有景点的最短距离利用迪杰斯特拉算法,由用户输入要查询的景点编号,查询该景点到其余所有景点的最短路径,以及最短路径长度。(4).从某一景点出发的最短连通路线利用Prim算法求最短连通图,也就是说,让用户输入起始的景点名称就可以查询由该景点出发的所有最短连通图。(5).用户输入出发点和目的地获取所有游览线路利用图的深度遍历,调用递归的思想逐个遍历景点,找到由出发点到目的地的所有游览路线,并打印出来。(6).两个景点之间的最短距离在菜单中通过switch语句进入排序功能,同样使用迪杰斯特拉算法求出图中两个节点之间的最短路径,这里由用户输入两个景点的名称就可查询两个景点之间的最短路径,以及路径长度。(7).修改景点信息,新西邮在菜单中通过switch语句进入修改功能,输入要修改的景点信息数目以及要修改景点的序号,输入新的信息以及修改的路径,即修改成功,重新查询就可查询到新的景点信息。(8).西邮沿途风景,ATM机介绍新鲜资讯在菜单中通过switch语句进入查询功能,改模块主要是方便用户了解西邮的推荐景点的位置以及常用的ATM机的位置,每天会更新“旭日苑”和“美食广场”推荐的美食,我觉得是个比较贴近生活的模块。(9).安全退出用exit(0)实现,退出导游系统;(10).main函数通过主函数main()将各个模块结合起来,main()函数主要调用了menu()菜单。四.详细设计1.功能函数的调用关系图2.各功能函数的数据流程图录入信息模块主函数main()Case1:显示校园全景图Case2:查看景点信息Case3:从一个景点到其余所有景点最短路径Case4:从一个景点出发的最短连通图Case5:出发点到目的地的所有路径Case6:两个景点之间的最短距离Case7:修改景点信息Case8:景点位置,ATM机介绍,今日资讯Case9:退出系统菜单menu()查找信息模块输入要查找的景点名称调用locate()函数所查询景点序号存在输出信息不存在返回主菜单选择2开始邻接矩阵存储申请空间依次设置景点编号输入名称输入路径长输入介绍景点信息存储在邻接矩阵中两景点最短路径模块两景点所有路径模块输入两个景点的名称调用path()函数由该景点开始试探有无到终点的路径,递归再找下一个顶点返回主菜单选择3输出两景点所有路径输入两个景点的名称调用Dijkstra()函数按景点序号依次比较找最短路径返回主菜单选择6输出最短路径和长度一景点出发的最短连通路径模块修改景点信息模块调用Newgraph()函数函数修改景点的基本信息,以及边的信息返回主菜单选择7修改成功,查询信息已变输入出发景点的名称调用Prim()函数从该景点出发选择与它关联的最小权值的边,加入到最小生成树中的集合返回主菜单选择4输出最小生成树3.重点设计及编码//利用Dijkstra算法求得从起点景点到终点景点的最短路线voidDijkstra(AdjMatrix*G,intstart,intend,intdist[],intpath[][MAX]){intmindist,i,j,k,t=1;for(i=0;iG-vexnum;i++)//初始化{dist[i]=G-arcs[start][i];if(G-arcs[start][i]!=INFINITY)path[i][1]=start;}path[start][0]=1;for(i=1;iG-vexnum;i++)//寻找各终点{mindist=INFINITY;for(j=0;jG-vexnum;j++)//选择路线最短的线路if(!path[j][0]&&dist[j]mindist){k=j;mindist=dist[j];}if(mindist==INFINITY)return;path[k][0]=1;for(j=0;jG-vexnum;j++)//修改路线{if(!path[j][0]&&G-arcs[k][j]INFINITY&&dist[k]+G-arcs[k][j]dist[j]){dist[j]=dist[k]+G-arcs[k][j];t=1;while(path[k][t]!=0)//记录最新的最短路线{path[j][t]=path[k][t];t++;}path[j][t]=k;path[j][t+1]=0;}}}for(i=0;i=G-vexnum;i++)if(i==end)break;printf(%s------%s最短路线为:,G-vex[start].name,G-vex[end].name);for(j=1;path[i][j]!=0;j++)printf(%s,G-vex[path[i][j]].name);printf(-%s距离为%dm\n,G-vex[end].name,dist[i]);}//寻找最短路线voidShortroute(AdjMatrix*G){charsight[MAX];intstart,end;intdist[MAX],path[MAX][MAX]={0};system(cls);menu1();printf(请输入起始景点:);scanf(%s,sight);start=Locate(G,sight);printf(请输入终止景点:);scanf(%s,sight);end=Locate(G,sight);Dijkstra(G,start,end,dist,path);}//修改创建新的图intNewgraph(AdjMatrix*G){intchangenum;//计数。用于记录要修改的对象的个数inti,m,n,t,distance,v0,v1;system(cls);menu1();printf(\n下面请输入你要修改的景点的个数:\n);scanf(%d,&changenum);while(changenum0||changenumG-vexnum){printf(\n输入错误!请重新输入);scanf(%d,&changenum);}for(i=0;ichangenum;i++){printf(\n请输入景点的编号:);scanf(%d,&m);t=Locate2(G,m);printf(\n请输入景点的名称:);scanf(%s,&G-vex[t].name);printf(\n请输入景点的简介:);scanf(%s,&G-vex[t].introduction);}printf(\n下面请输入你要更新的边数);scanf(%d,&changenum);while(changenum0||changenumG-arcnum){printf(\n输入错误!请重新输入);scanf(%d,&changenum);}printf(\n下面请输入更新边的信息:\n);for(i=1;i=changenum;i++){printf(\n修改的第%d条边的起点序号终点序号长度为:,i);scanf(%d%d%d,&v0,&v1,&distance);m=Locate2(G,v0);n=Locate2(G,v1);if(m=0&&n=0){G-arcs[m][n]=distance;G-arcs[n][m]=G-arcs[m][n];}}return1;}//打印序号为m,n景点间的长度不超过8个景点的路径voidpath(AdjMatrix*G,intm,intn,intk){ints,x=0;intt=k+1;//t记载路径上下一个中间顶点在d[]数组中的下标if(d[k]==n&&k8)//d[k]存储路径顶点。若d[k]是终点n且景点个数=8,则输出{//递归出口,找到一条路径for(s=0;sk;s++)printf(%s---,G-vex[d[s]].name);//输出该路径。s=0时为起点mprintf(%s,G-vex[d[s]].name);//输出最后一个景点名printf(\n\n);}else{s=0;while(sG-vexnum)//从第m个顶点,试探至所有顶点是否有路径{if((G-arcs[d[k]][s]INFINITY)&&(visited[s]==0))//初态{visited[s]=1;d[k+1]=s;//存储顶点编号s至d[k+1]中path(G,m,n,t);//打印出一条m至n的路径visited[s]=0;}s++;//试探从下一个顶点s开始是否有到终点的路径}}}//打印两景点间的景点个数不超过8的所有路径intAllpath(AdjMatrix*G){intk,m,n;charsight1[MAX];charsight2[MAX];system(cls);menu1();printf(\n\n请输入你要查询的两个景点名称:\n\n);scanf(%s%s,sight1,sight2);printf(\n\n);m=Locate(G,sight1);//确定该顶点是否存在。若存在,返回该顶点编号n=Locate(G,sight2);d[0]=m;//存储路径起点m(intd[]数组是全局变量)for(k=0;kG-vexnum;k++)//全部顶点访问标志初值设为0visited[k]=0;visited[m]=1;//第m个顶点访问标志设置为1path(G,m,n,0);//k=0,对应起点d[0]==m。k为d[]数组下标return1;}五.测试数据及运行结果1.正常测试数据和运行结果2.异常测试数据及运行结果六.调试情况,设计技巧及体会1.改进方案这次课程设计时间比较短,问题比较多,最大的问题就是求所有路径和最短路径,这个花了我很多时间,通过实践知道调试的时候可以多加一些printf()语句查错。另外自己再外观上通过调用DOS命令玩了很多花样比如说换背景颜色。需要改进的就是存储问题,我用的是初始化,这样修改不是很方便,我想如果有时间的话,我会改成文件存储,这样会更好,更方便。2.体会通过这次课程设计,我发现自己对图还很不熟,栈的运用也不是很娴熟,在这之前曾编过两个跟图有关的题,做这个的时候才不那么束手无策。发现其实程序要写得好,关键在于它的移植性,可以多次调用,代码才会简单。有些程序就是在我以前的程序上作了修改直接拿过来用的。通过这次课程设计发现自己连c语言的门都没入。C语言要学好并不是那么简单,光听