景区旅游信息管理系统1.1.1项目需求在旅游景区,经常会遇到游客打听从一个景点到另一个景点的最短路径和最短距离,这类游客不喜欢按照导游图的线路来游览,而是挑选自己感兴趣的景点游览。为于帮助这类游客信息查询,就需要计算出所有景点之间最短路径和最短距离。算法采用迪杰斯特拉算法或弗洛伊德算法均可。建立一个景区旅游信息管理系统,实现的主要功能包括制订旅游景点导游线路策略和制订景区道路铺设策略。任务中景点分布是一个无向带权连通图,图中边的权值是景点之间的距离。(1)景区旅游信息管理系统中制订旅游景点导游线路策略,首先通过遍历景点,给出一个入口景点,建立一个导游线路图,导游线路图用有向图表示。遍历采用深度优先策略,这也比较符合游客心理。(2)为了使导游线路图能够优化,可通过拓朴排序判断图中有无回路,若有回路,则打印输出回路中的景点,供人工优化。(3)在导游线路图中,还为一些不愿按线路走的游客提供信息服务,比如从一个景点到另一个景点的最短路径和最短距离。在本线路图中将输出任意景点间的最短路径和最短距离。(4)在景区建设中,道路建设是其中一个重要内容。道路建设首先要保证能连通所有景点,但又要花最小的代价,可以通过求最小生成树来解决这个问题。本任务中假设修建道路的代价只与它的里程相关。因此归纳起来,本任务有如下功能模块:创建景区景点分布图;输出景区景点分布图(邻接矩阵)输出导游线路图;判断导游线路图有无回路;求两个景点间的最短路径和最短距离;输出道路修建规划图。主程序用菜单选项供用户选择功能模块。1.1.2设计流程主程序采用设计主菜单调用若干功能模块,同时在主程序中定义两个邻接链表类型变量G和G1,作为调用子函数的参数。建图子模块建立无向带权图,输入顶点信息和边的信息,输出邻接链表G。由于是无向边,输入一条边时构建两条边。输出图子模块:从邻接链表g转换成邻接矩阵a,并输出邻接矩阵a。图中边的权值∞用32767表示。遍历子模块:通过遍历图G,只得到遍历的顶点序列。我们先将顶点序列存在数组vex中,然后再转换成导游线路存入数组vex1中,最后生成导游线路图G1(同样用邻接链表存储,供拓朴排序用)。将遍历顶点序列转换成导游线路。图10-43(a)(b)(c)三个无向图的深度优先搜索遍历的结果均为v1→v2→v3→v4。但它们的导游线路图却不同。图(a)的导游线路图为v1→v2→v3→v4,与遍历结果相同。图(b)的导游线路图为v1→v2→v3→v2→v4,图(c)的导游线路图为v1→v2→v3→v2→v1→v4。遍历结点序列与导游线路图转换的策略:设遍历结果为v1→v2→…→vi→vi+1→…→vn对于结点vi和vi+1,如果vi和vi+1存在边,则直接转换。否则,加入边vi→vi-1,如果vi-1和vi+1存在边,则加入边vi-1→vi+1。再否则,加入边vi-1→vi-2,如果vi-2和vi+1存在边,则加入边vi-2→vi+1。如果vi-2和vi+1还不存在边,继续回溯,一定能找到某个整数k(因为景点分布图是连通图),使得vi-k和vi+1存在边,则加入边vi-k→vi+1。在本任务中,转换后的线路图存于数组vex1中。流程图见10-29。拓朴排序子模块流程图,见图10-39源程序,参见10.7节的samp10-8.c。求最短路径子模块流程图:见10-34。源程序,参见10.6节的samp10-6.c。求最小生成树子模块流程图:见19-33。源程序,参见10.6节的samp10-5.c。1.1.3数据结构景点的信息包括景点的名称和近邻景点之间的通路和距离。用邻接链表存储景点分布图的信息。(带权无向)图的邻接链表/***************************************************************//*程序功能:建立一个旅游景区管理系统,实现旅游路线选择*//*景区道路优化等功能*//***************************************************************/#include“stdio.h”#include“stdlib.h”#include“string.h”#defineMAX_EDGE_NUM100/*定义图的最大边数*/#defineMAX_VERTEX_NUM20#defineMAXNUM32767typedefcharVertex_type[10];typedefstructnode/*边表结点*/{intadjvex;/*邻接点域*/intweight;structnode*next;/*指向下一个邻接点的指针域*/}Edge_node;typedefstruct/*顶点表结点*/{Vertex_typevertex;/*顶点域,存放景点名称*/Edge_node*firstedge;/*边表头指针*/}Vertex_node;typedefstruct{Vertex_nodeadjlist[MAX_VERTEX_NUM];/*邻接表*/intn,m;/*顶点数和边数*/}Lgraph;边的类型定义在求最小生成树时,用到边的定义。typedefstruct{inti;/*顶点vi的序号*/intj;/*顶点vi的序号*/intweight;}Edge_type;1.1.4程序清单主程序源程序/*************************************************************//*函数名:main*//*入口参数:无*//*返回值:无*//*************************************************************/voidmain(){Lgraph*g,*g1;intsele;voidcreate_graph();voidoutput_graph();voiddfs_main();voidtopo_sort_main();voidmin_distance_main();voidmin_tree();g=(Lgraph*)malloc(sizeof(Lgraph));g-m=0;g1=(Lgraph*)malloc(sizeof(Lgraph));while(1){system(cls);printf(“\n\n******景区旅游管理信息系统******\n”);printf(“1.输入景点分布图\n”);printf(“2.输出景点分布图邻接矩阵\n”);printf(“3.生成导游线路图\n”);printf(“4.输出导游线路图中回路\n”);printf(“5.求两景点间最短路径和最短距离\n”);printf(“6.输出景区道路修建规划图\n”);printf(“0.退出\n”);printf(“请选择功能序号:”);scanf(“%d”,&sele);printf(\n\n***************************************************\n\n);switch(sele){case1:create_graph(g);break;case2:output_graph(g);break;case3:dfs_main(g,g1);break;case4:topo_sort_main(g1);break;case5:min_distance_main(g);break;case6:min_tree(g);break;case0:exit(0);}getchar();printf(按回车键继续......);getchar();}}建图子模块源程序参见10.3节的create_graph()函数。输出图子模块/**************************************************************//*函数名:output_graph*//*函数功能:输出图G的邻接矩阵*//*入口参数:g---邻接链表*//*返回值:无*//**************************************************************/voidoutput_graph(Lgraph*g){inti,j,n;inta[MAX_VERTEX_NUM][MAX_VERTEX_NUM];Edge_node*p;if(g-n==0){printf(“景点分布图未输入,无法输出!\n”);return;}for(i=0;ig-n;i++)for(j=0;jg-n;j++)if(i==j)a[i][j]=0;elsea[i][j]=MAXNUM;for(i=0;ig-n;i++){p=g-adjlist[i].firstedge;while(p!=NULL){j=p-adjvex;a[i][j]=p-weight;p=p-next;}}printf(景点分布图邻接矩阵为:\n\n);printf(%8s,);for(i=0;ig-n;i++)printf(%8s,g-adjlist[i].vertex);for(i=0;ig-n;i++){printf(%8s,g-adjlist[i].vertex);for(j=0;jg-n;j++)printf(%9d,a[i][j]);printf(“\n”);}}遍历子模块/**************************************************************//*函数名:dfs_main*//*函数功能:生成导游线路图*//*入口参数:g--景点分布图*//*g1—导游线路图*//*返回值:无*//**************************************************************/voiddfs_main(Lgraph*g,Lgraph*g1){intvisited[MAX_VERTEX_NUM];intx,i;intvex[MAX_VERTEX_NUM];intj,k,i1,tag;intvex1[MAX_VERTEX_NUM];Edge_node*p,*q;for(i=0;iMAX_VERTEX_NUM;i++)visited[i]=0;if(g-n==0){printf(“景点分布图未输入,无法生成导游线图!\n”);return;}do{printf(请输入口景点序号:);scanf(%d,&x);if(x=1&&x=g-n){x--;break;}elseprintf(景点号输入有误,请重新输入!\n);}while(1);j=0;dfs(g,x,visited,vex,&j);//每次调用时,j初始化为0/*构建游览线路,存放在数组Vex1*/i1=0;for(i=0;ig-n-1;i++){j=vex[i+1];tag=1;k=0;while(tag){vex1[i1++]=vex[i+k];p=g-adjlist[vex[i+k]].firstedge;while(p!=NULL&&p-adjvex!=j)/*判断vi+k与vj之间有没有边*/p=p-next;if(p==NULL)k--;/*若vi+k与vj之间没有边回溯*/elsetag=0;}}vex1[i1++]=j;/*建立游览线路图的邻接链表G1,供拓朴排序用*/for(i=0;ig-n;i++){strcpy(g1-adjlist[i].vertex,g-adjlist[i].vertex);g1-adjlist[i].firstedge=NULL;}for(k=0;ki1-1;k++){i=vex1[k];j=vex1[k+1];p=(Edge_node*)malloc(sizeof(Edge_node));p-adjvex=j;p-weight=1;/*建立游览线路图时,不考虑边的