通过参与本课程设计,你将有机会实现一个学校地图信息库系统。这个系统不仅能够让你充分发挥自己的想象力和动手能力,还能让你在实践中掌握多种计算机科学的核心技能。
- 最短路径算法:在本课程中,你将学习并掌握两种常用的最短路径算法——Dijkstra算法和Floyd算法。这两种算法在解决图论中的最短路径问题时具有广泛的应用。通过实践,你将深入理解这两种算法的原理和应用方法,为后续的编程项目打下坚实的基础。
- 文件操作:在开发过程中,你将学会如何利用文件来保存程序运行的数据信息。这一技能对于数据的持久化存储至关重要,无论是为了后续的分析还是为了方便用户查看历史数据,都离不开对文件的操作。
- 二维数组与字符串:二维数组是计算机科学中的一种基本数据结构,它可以用来表示各种复杂的数据关系。在本课程中,你将通过实际的项目需求,深入理解和掌握二维数组的使用。同时,你也将学习到如何在程序中处理和操作字符串,这在数据处理和用户交互中都是非常关键的技能。
- 文件操作代码:除了基本的打开文件和保存文件操作,你还将学会如何在程序中进行输入操作。这些技能将帮助你更好地与用户进行交互,使得你的程序更加易用和灵活。
- 全局变量的定义和使用:全局变量在程序设计中起着重要的作用,它们可以在程序的不同部分之间共享数据。在本课程中,你将学习如何定义和使用全局变量,以及如何在保证程序可读性和可维护性的同时,合理地使用全局变量。
1.核心功能是最短路径的检索和输出。该功能可以由用户给定的点到全部点的最短路径,并提供景点代号、名称、简介等信息供用户查询。通过这个功能,用户可以方便地找到从当前位置到其他景点的最短路径,以便更高效地安排他们的行程。
2.为来访客人提供图中任意景点相关信息的查询。该功能可以根据用户输入的起始景点编号,求出该景点到其他景点的最短路径线路及距离。这样,游客可以根据他们感兴趣的景点,快速了解到达其他景点的最佳路线,以便更好地规划他们的游览路线。
3.为校园平面图增加和删除景点或边,修改边上的权值等。这个功能允许管理员对校园平面图进行维护和更新。他们可以添加新的景点或边,或者删除不再存在的景点或边。此外,他们还可以修改边上的权值,以反映不同景点之间的实际距离或通行时间。这样,校园导航小助手可以提供最准确和最新的导航信息,以满足用户的需求。
整体设计如下图
实现了通过文件的方式保存地点信息和地点的存放景点代号、名称、简介等信息供用户查询,为来访客 人提供图中任意景点相关信息的查询距离信息分别为tu.txt、tu1.txt和最短路径FloydALGraph.txt,在程序进入时自动加载完成数据,将文件数据保存在相应的数组里。
将函数名放在主函数里,在开启程序时完成自动载入数据。
以模块化方式编写程序,可以使其层次清晰,易于调试和维护,让程序简而不繁。
总的项目在完成任务的基础上添加了一些小功能,让用户体验更上一层楼,总的效果符合个人所想和设计的要求,算法上的总的时间复杂度在区间(O(1)到O(N2))上,掌握了文件的运用和Dijistra算法的运用,在算法的基础上还学会了如何让代码更整洁,也学会对代码有很好的命名,让人一目了然,也学会了运用cmd里的特殊代码如清屏函数System(”cls”)等。优点是可以很好的对代码有个很好的理解和算法的运用。
改进:可继续分多个的模块实现该程序,使其程序更完善,还可以将图信息变成word文档或者变成一副图画的方式让人更容易读解,可以方便用户体验或是直接在程序基础上设计一个打印功。
完成了存放景点编号,名称,介绍信息来提供用户查询,完成了根据用户需求输入其实景点编号,输出到其他所有景点的最短路线和距离,也完成了任意两点间最短路径的检索,其算法是用Dijkstra实现的。
如图2所示,是由Dijkstra核心算法完成两点之间的最短路径。
点到所有点的最短路径距离(部分图)如图
Dijkstra核心算法代码,如图
在此基础上添加了增点,加边,删点,删边,打印邻接矩阵(下图)并提示用户是否保存在txt文本里,其次还添加了退出程序保存文件,存放为txt文本,文本的编码是使用ASNI编码的。
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<algorithm> #include<errno.h> //#define m 5201314 #define max 999999 int ml[100]; int djs[110]; struct node { int number; char name[40]; char introduce[500]; int maxcount; int digitor; }place[100],place1[100]; struct Tnode { int distance; int bia; }map1[100][100],map2[100][100]; void inset(char* pFileName){ FILE *err; FILE* pFile; err = fopen(pFileName, "r");//读取名为pFileName的文本文件 if (err == 0)//判断文件是否打开是否成功 printf("文件打开失败\n"); else printf("文件打开成功\n"); // double data[10][3];//先只考虑文件中的数据为10行3列的小数 int i=0; while((fscanf(err,"%d",&place[i].number))&&place[i].number!=EOF){ place1[i].number=place[i].number; // getchar(); fscanf(err,"%s",place[i].name); strcpy(place1[i].name,place[i].name); // getchar(); fscanf(err,"%s",place[i].introduce); strcpy(place1[i].introduce,place[i].introduce); place[i].digitor=place1[i].digitor=0; // getchar(); // printf("%d %s %s\n",place[i].number,place[i].name,place[i].introduce); i++; //fscanf_s函数固定格式读取文本中的数据; } place[0].maxcount=place1[0].maxcount=i; // for (i = 0;i < place[0].maxcount;i++) {//将读取的数据输出 for (int j = 0;j < 3;j++) // printf("%s",place[i].introduce); // printf("\n"); // } fclose(err); } void inset1(char* pFileName){ FILE *err; err = fopen(pFileName, "r"); if (err == 0) printf("文件打开失败\n"); else printf("文件打开成功\n"); for(int i=0;i<place[0].maxcount;i++){ for(int j=0;j<place[0].maxcount;j++){ fscanf(err,"%d",&map1[i][j].distance); // fgetchar(); map2[i][j].distance=map1[i][j].distance; map1[i][j].bia=map2[i][j].bia=0; } } fclose(err); } void floyd(int n){ for (int i = 0; i < n; i++) {// floyd。 for (int j = 0; j <n; j++) { for (int k = 0; k <n; k++) { if (map2[j][i].distance + map2[i][k].distance <map2[j][k].distance) { map2[j][k].distance = map2[j][i].distance + map2[i][k].distance; } } } } } void lujing1(){ FILE *err=fopen("tu1.txt","w"); if (err == 0) printf("文件打开失败\n"); else printf("文件打开成功\n"); for(int i=0;i<place1[0].maxcount;i++){ fprintf(err,"%d\n%s\n%s\n",place1[i].number,place1[i].name,place1[i].introduce); } fclose(err); } void lujing2(){ FILE *err=fopen("最短路径FloydALGraph.txt","w"); if (err == 0) printf("文件打开失败\n"); else printf("文件打开成功\n"); for(int i=0;i<place1[0].maxcount;i++){ for(int j=0;j<place1[0].maxcount;j++){ fprintf(err,"%d ",map2[i][j].distance); } fprintf(err,"\n"); } fclose(err); } void DJS(int n,int m){ //迪杰斯特拉算法 int a,b,c,d,p,min; int x[110],y[110]; memset(x,-1,sizeof(x)); memset(djs,0,sizeof(djs)); memset(y,0,sizeof(y)); memset(ml,0,sizeof(ml)); for(a=0;a<place[0].maxcount;a++){ djs[a]=map2[n][a].distance; if(djs[a]<max){ x[a]=n; } if(a==n){x[a]=99999;} } ml[n]=1; // int fd=n; for(a=1;a<place[0].maxcount;a++){ min=max; for(b=0;b<place[0].maxcount;b++){ if(ml[b]==0&&djs[b]<min){ min=djs[b]; c=b; } } ml[c]=1; // fd=c; //标记该点 for(d=0;d<place[0].maxcount;d++){ if(ml[d]==0&&djs[d]>djs[c]+map2[c][d].distance){ x[d]=c; djs[d]=djs[c]+map2[c][d].distance; } } } d=m; a=0; while(x[d]!=n){ y[a]=x[d]; d=x[d]; a++; } printf("\n"); c=a-1; printf("路线为:\n"); printf("%s--->",place[n].name); for(a=c;a>=0;a--){ printf("%s--->",place[y[a]].name); } printf("%s\n",place[m].name); printf("最短路径长度为:%d 米\n",djs[m]); } void lb(){ system("cls"); //清屏 printf("\n\n\n"); printf("\t\t\t\t\t * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * * * * * *\n"); printf("\t\t\t\t\t * * *景点列表* * *\n"); printf("\t\t\t\t\t * ************************************************************************ *\n"); printf("\t\t\t\t\t * * * *\n"); printf("\t\t\t\t\t * * <1>学校北门 <2>学校南北门 <3>国际教育学院 <4>数字媒体艺术学院 * *\n"); printf("\t\t\t\t\t * * * *\n"); printf("\t\t\t\t\t * * <5>行政楼 <6>信工楼 <7>体育场 <8>商管楼 <9>A座教学楼 * *\n"); printf("\t\t\t\t\t * * * *\n"); printf("\t\t\t\t\t * * <10>中区学生宿舍 <11>继续教育学院大楼 <12>B座教学楼 <13>游泳馆 * *\n"); printf("\t\t\t\t\t * * * *\n"); printf("\t\t\t\t\t * * <14>报告厅、阶梯教室 <15>大礼堂、体育馆 <16>1食堂 <17>新图书馆 * *\n"); printf("\t\t\t\t\t * * * *\n"); printf("\t\t\t\t\t * * <18>2食堂 <19>东区学生宿舍 <20>教授楼 <21>教工宿舍 <22>西区学生宿舍* *\n"); printf("\t\t\t\t\t * * * *\n"); printf("\t\t\t\t\t * * <23>3食堂 <24>C座教学楼 <25>E座教学楼 <26>5F座教学楼 <27>实验楼 * *\n"); printf("\t\t\t\t\t * * * *\n"); printf("\t\t\t\t\t * * <28>H座教学楼 <29>小镇 * *\n"); printf("\t\t\t\t\t * ************************************************************************ *\n"); printf("\t\t\t\t\t * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * * * * * *\n"); printf("\n\n\n"); } //void qing(){ // int n=place[0].maxcount; // for(int i=0;i<n;i++){ // ml[i]=0; // } //} void gn6(){ int a,b,n,m; system("cls"); lb(); while(1){ printf("请输入初始景点 : "); scanf("%d",&n); if(n>=1&&n<=place[0].maxcount){ system("cls"); for(a=0;a<place[0].maxcount;a++){ if(a!=n-1){ DJS(n-1,a); } } printf("\n\n按回车键返回至主界面\n\n"); getchar();getchar(); break; } else{ printf("输入错误,无该景点,请重新输入!!!"); scanf("%d",&n); } } // qing(); } void lhj(int x){//游览路线 int n=place[0].maxcount; int i,j,k=x,min=0,coune=0,mincount; printf("路线应为:"); printf("%s--->",place[x].name); place[x].digitor=1; for(i=1;i<n;i++){ min=max; k=x; int mnb=-1; for(j=0;j<n;j++){ if(j!=k){ if(min>map2[k][j].distance&&place[j].digitor==0){ mnb=j; mincount=map2[k][j].distance; } } } coune=coune+mincount; if(mnb!=-1&&i<n-2){ printf("%s--->",place[mnb].name); place[mnb].digitor=1; k=mnb; }else if(mnb!=-1&&i==n-2){ printf("%s.",place[mnb].name); place[mnb].digitor=1; k=mnb; } } printf("\n总路程为 %d m。\n",coune); } void xiao1(char* pFileName){//在次建图 FILE *err; FILE *pFile; err = fopen(pFileName, "w");//读取名为pFileName的文本文件 if (err == 0)//判断文件是否打开是否成功 printf("文件打开失败\n"); else printf("文件打开成功\n"); int i=0; scanf("%d",&place1[i].number); while(place1[i].number!=-1){ getchar(); scanf("%s",place1[i].name); getchar(); scanf("%s",place1[i].introduce); fprintf(err,"%d\n%s\n%s\n",place1[i].number,place1[i].name,place1[i].introduce); place1[i].digitor=0; i++; scanf("%d",&place1[i].number); } place1[0].maxcount=i; fclose(err); } void xiao2(int x){//删除节点 int n=place1[0].maxcount; for(int i=0;i<n;i++){ if(i>x){ place1[i-1].number=place1[i].number-1; strcpy(place1[i-1].name,place1[i].name); strcpy(place1[i-1].introduce,place1[i].introduce); } if(i==n-1){place1[i].number=-1;} } for(int i=0;i<n;i++){ if(i>x){ for(int j=0;j<n;j++){ map2[i-1][j].distance=map2[i][j].distance; } } } for(int i=0;i<n;i++){ if(i>x) for(int j=0;j<n-1;j++){ map2[j][i-1].distance=map2[j][i].distance; } } printf("删成功。"); lujing1(); lujing2(); } void xiao3(int x,int y){//删除边 // FILE* err; // err=fopen(pFileName,"r"); // int n=place[0].maxcount; // for(int i=0;i<n;i++){ // for(int j=0;j<n;j++){ // fscanf(err,"%d",&map2[i][j].distance); // fgetchar(); // } // } // fclose(err); for(int i=0;i<place1[0].maxcount;i++){ for(int j=0;j<place1[0].maxcount;j++){ if((i==x&&j==y)||(i==y&&j==x)){ map2[i][j].distance=max; } map2[i][j].bia=0; } } printf("删成功。"); lujing2(); // FILE* dsw; // dsw=fopen(pFileName,"a"); // for(int i=0;i<n;i++){ // for(int j=0;j<n;j++){ // fprintf(dsw,"%d",map2[i][j].distance); // char fg; // fputchar(fg); // } // } // fclose(dsw); } void xiao4(){//增加节点 int n=place1[0].maxcount; place1[n].number=n+1; printf("\n请输入名字:"); scanf("%s",place1[n].name); printf("\n请输入介绍:"); scanf("%s",place[n].introduce); place1[0].maxcount++; n=place1[0].maxcount; for(int j=0;j<n;j++){ scanf("%d",map2[n-1][j].distance); map2[j][n-1].distance=map2[n-1][j].distance; } lujing1(); lujing2(); } void xiao5(int x,int y,int w){//增加边 // FILE* err; // err=fopen(pFileName,"a"); for(int i=0;i<place[0].maxcount;i++){ for(int j=0;j<place[0].maxcount;j++){ if(i==x&&j==y||i==y&&j==x){ map2[i][j].distance=w; } } } lujing2(); // fclose(err); } void xiao6(){//更新信息 printf("1:改地址名 2:改距离\n"); printf("\n你想要干:"); int x; int number; scanf("%d",&x); if(x==1){ printf("\n请输入序号:"); scanf("%d",&number); // FILE* err; // err=fopen(pFileName,"r"); // int n=place[0].maxcount; // for(int i=0;i<n;i++){ // fscanf(err,"%d\n%s\n%s\n",&place[i].number,place[i].name,place[i].introduce); // } // fclose(err); int n=place1[0].maxcount; for(int i=0;i<n;i++){ if(i==number){ printf("\n请更改名字:"); scanf("%s",place1[i].name); getchar(); printf("\n请填入介绍:"); scanf("%s",place1[i].introduce); } } lujing1(); // FILE* dsw; // dsw=fopen(pFileName,"w"); // for(int i=0;i<n;i++){ // for(int j=0;j<n;j++){ // fprintf(dsw,"%d",map2[i][j].distance); // char fg; // fputchar(fg); // } // } // fclose(dsw); }else if(x==2){ printf("\n请输入起点:"); int head,end; scanf("%d",&head); printf("\n请输入终点:"); scanf("%d",&end); printf("\n请输入变后的距离:"); int distance,n=place1[0].maxcount; scanf("%d",&distance); for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ if(i==head&&j==end||i==end&&j==head){ map2[i][j].distance=distance; } } } lujing2(); } } void xiao7(){//打印邻接矩阵 for(int i=0;i<place1[0].maxcount;i++){ for(int j=0;j<place1[0].maxcount;j++){ printf("%d ",map2[i][j].distance); } printf("\n"); } } int main(){ int i,j,k,l,n,m,x; inset("tu.txt"); inset1("最短路径FloydALGraph.txt"); system("cls"); printf("----------欢迎使用校园导航小助手-----------\n"); printf(" 欢迎来到学校地图! \n\n\n"); printf(" 菜 单 选 择\n"); printf(" 1、学校景点介绍 2、查看游览路线\n"); printf(" 3、查询景点间最短路径 4、景点信息查询\n"); printf(" 5、更改图信息 6、查询景点间可行路径\n"); printf(" 7、打印邻接矩阵 8、退出\n"); printf("--------------------------------------------\n"); printf("请输入你的选择:"); scanf("%d",&x); while((int)x<1||(int)x>=9){ printf("未识别出选项,抱歉请再次输入\n"); scanf("%d",&x); } while(x>=1&&x<9){ if(x==1){ for(i=0;i<place[0].maxcount;i++){ printf("%d %s %s\n",place[i].number,place[i].name,place[i].introduce); } }else if(x==2){ floyd(place[0].maxcount); printf("请输入一个起始景点的编号:"); scanf("%d",&m); lhj(m); }else if(x==3){ lb(); printf("请输入一个起始景点的编号:"); scanf("%d",&k); printf("\n请输入一个终点景点的编号:"); scanf("%d",&l); DJS(k-1,l-1); }else if(x==4){ printf("请输入你要查询的景点:"); scanf("%d",&m); printf("%d %s %s\n",place[m].number,place[m].name,place[m].introduce); }else if(x==5){ printf("请问是要\n"); printf("(1)在次建图 (2)删除节点 (3)删除边\n"); printf("(4)增加节点 (5)增加边 (6)更新信息\n"); printf("(7)打印邻接矩阵 (8)返回?\n"); int y; scanf("%d",&y); while(y>=1&&y<9){ if(y==1){ // xiao1(); xiao1("tu1.txt"); }else if(y==2){ printf("删除的点:"); scanf("%d",&i); while(i<0||i>place1[0].maxcount){ printf("抱歉你所输入的点不存在,请重新输入"); scanf("%d",&i); } xiao2(i); // xiao2("D:\\tu1.txt",i); }else if(y==3){ printf("删除的边:"); scanf("%d %d",&i,&j); xiao3(i,j); // xiao3("最短路径FloydALGraph.txt",i,j); }else if(y==4){ printf("增加的点:"); // xiao4("tu1.txt",i); xiao4(); }else if(y==5){ printf("增加的边:"); int w; scanf("%d %d %d",&i,&j,&w); xiao5(i,j,w); // xiao5("最短路径FloydALGraph.txt",i,j,w); }else if(y==6){ // xiao6("tu1.txt"); xiao6(); }else if(y==7){ xiao7(); }else if(y==8){break; } printf("(1)在次建图 (2)删除节点 (3)删除边\n"); printf("(4)增加节点 (5)增加边 (6)更新信息\n"); printf("(7)打印邻接矩阵 (8)返回?\n"); printf("你接下来要干嘛?"); scanf("%d",&y); } }else if(x==6){ gn6(); }else if(x==7){ for(i=0;i<place[0].maxcount;i++){ for(j=0;j<place[0].maxcount;j++){ if(map1[i][j].distance<max)printf("[%d][%d]%d ",i,j,map1[i][j].distance); else printf("[%d][%d]无路 ",i,j); } printf("\n"); } }else if(x==8){ // system("cls"); printf("\t\t\t\t\t ****************************************************\n"); printf("\t\t\t\t\t * 感谢使用 *\n"); printf("\t\t\t\t\t * *\n"); printf("\t\t\t\t\t * *\n"); printf("\t\t\t\t\t * *\n"); printf("\t\t\t\t\t * *\n"); printf("\t\t\t\t\t * *\n"); printf("\t\t\t\t\t * *\n"); printf("\t\t\t\t\t * *\n"); printf("\t\t\t\t\t ****************************************************\n"); printf("\n\n\n\n\n"); break; } inset("tu1.txt"); inset1("最短路径FloydALGraph.txt"); printf("是否继续?1:0\n"); int sa; printf("你的选择:"); scanf("%d",&sa); if(sa==1)system("cls"); if(sa==1){ printf("----------欢迎使用校园导航小助手-----------\n"); printf(" 欢迎来到学校地图! \n\n\n"); printf(" 菜 单 选 择\n"); printf(" 1、学校景点介绍 2、查看游览路线\n"); printf(" 3、查询景点间最短路径 4、景点信息查询\n"); printf(" 5、更改图信息 6、查询景点间可行路径\n"); printf(" 7、打印邻接矩阵 8、退出\n"); printf("--------------------------------------------\n"); printf("请输入你的选择:"); scanf("%d",&x); }else{ x=8; } } return 0; }