本人是某大学计算机的菜鸡,在数据结构上机课作业完成过程中,曾上网找了很多类似代码寻找思路,但是网上的代码太繁琐,而且都不是很好理解,因此在自己完成以后就写了这么一个博客,提供一种比较简单的程序代码,希望对那些还在数据结构中头痛的同学一点帮助。
        问题描述:设计以校园导游程序,为来访的客人提供各种信息查询服务。

设计要求:

(1)设计自己所在学校的校园平面图(所含景点不少于十个),顶点信息包括名称、简介等,边的信息包括路径长度等。

(2)为来访的客人提供景点信息查询服务。

(3)为来访的客人提供从当前顶点出发前往景点的路线查询服务,包括最短路径及有可能的简单路径。
 附图:

其实整个题目很简单,主要就是求最短路径的算法问题,在这里由于这个题需要输出所有路径,因此直接选取暴力枚举的方法,把所有的路径都给枚举出来,最后将最小的路径保存起来,最后单独进行输出就好:

     if(b==w) {                                  //如果找到终点则进行输出,否则继续查找for(p=0;p<k;p++){printf("%d->",G->a[p]);}printf("%d  ",G->a[k]);printf("路线总长:%dkm\n",sum);if(sum<G->minrude){     //若当前路径总长小于最小值,则对最短路径进行更新G->r=k;G->minrude=sum;for(p=0;p<=k;p++){G->min[p]=G->a[p];}}return ;}else{for(j=1;j<=10;j++){if(G->arc[b][j]<5000&&G->vexs[j].park==0){ k++;G->a[k]=j;sum+=G->arc[b][j];             G->vexs[j].park=1;RudeGraph(G,j,w,k,sum);    //通过递归对所有路径进行深度搜索k--;                       //递归返回这一层后对顶点信息进行重新初始化G->vexs[j].park=0; sum-=G->arc[b][j];}}}

值得注意的是,这段暴力枚举的代码使用了邻接矩阵的思想,从邻接矩阵的第一行第一个点对后面点的不断递归查找,返回上一层时候对顶点信息初始化为递归前的状态还是比较细节的。

完整代码如下:

#include <stdio.h>
#include <stdlib.h>#define M 5000              //假设两顶点之间没有路径,用5000来表示typedef struct vexsinfo     //存放顶点信息的结构体
{int park;               //访问的标志,park=0是未被访问过int num;                //景点的编号char name[32];          //景点的名称char introduction[256]; //景点的介绍
}vexsinfo;typedef struct MGraph
{int r;                  //记录最短路径访问过的景点数目int minrude;            //记录最短路径的长度int min[50];            //记录最短路径经过的顶点信息int a[50];              //记录路线的数组vexsinfo vexs[50];      //存放顶点编号的数组,用vexsinfo结构体的变量vexsinfo定义,可以用//该数组存放顶点信息            int arc[50][50];        //存放两点之间权值的邻接矩阵int v,e;                //定点数和边数
} MGraph;MGraph* CreateGraph()
{MGraph *G;int i,j,k;G=(MGraph*)malloc(sizeof(MGraph));//初始化访问标志for(i=0;i<10;i++){G->vexs[i].park=0;}//初始化顶点数目和路线数目G->v=10;G->e=13;//给景点数组编号for(i=1;i<=G->v;i++)G->vexs[i].num=i;for(j=1;j<=10;j++)for(k=1;k<=10;k++){G->arc[j][k]=M;}//初始化矩阵,赋予每条边权值G->arc[1][2]=G->arc[2][1]=1;G->arc[1][3]=G->arc[3][1]=3;G->arc[1][10]=G->arc[10][1]=8;G->arc[2][6]=G->arc[6][2]=2;G->arc[4][3]=G->arc[3][4]=1;G->arc[4][5]=G->arc[5][4]=1;G->arc[9][5]=G->arc[5][9]=2;G->arc[6][7]=G->arc[7][6]=1;G->arc[7][8]=G->arc[8][7]=2;G->arc[10][7]=G->arc[7][10]=3;G->arc[8][9]=G->arc[9][8]=2;G->arc[8][10]=G->arc[10][8]=2;G->arc[9][10]=G->arc[10][9]=3;//初始化顶点信息strcpy(G->vexs[1].name ,"校  门");strcpy(G->vexs[2].name ,"综合楼");strcpy(G->vexs[3].name ,"科技馆");strcpy(G->vexs[4].name ,"月牙湖");strcpy(G->vexs[5].name ,"咖啡屋");strcpy(G->vexs[6].name ,"篮球场");strcpy(G->vexs[7].name ,"体育馆");strcpy(G->vexs[8].name ,"图书馆");strcpy(G->vexs[9].name ,"学生活动中心");strcpy(G->vexs[10].name ,"三炷香");strcpy(G->vexs[1].introduction ,"曾经是亚洲第一大校门,现因临沂大学重建以后成为亚洲队二大校门");strcpy(G->vexs[2].introduction ,"老师和领导们办公的地方");strcpy(G->vexs[3].introduction ,"里面有学校的校史馆,记录着杭电发展的历史");strcpy(G->vexs[4].introduction ,"学校里面唯一的湖,旁边有一片草地,是情侣们经常出没的地方,里面有许多鸭子游来游去");strcpy(G->vexs[5].introduction ,"咖啡屋是学生在运营的,里面每天都会有学生和老师在学习和娱乐");strcpy(G->vexs[6].introduction ,"篮球热爱者的天堂,篮球比赛都在这里举办");strcpy(G->vexs[7].introduction ,"很多明星来开演唱会时会在体育馆内进行,其次篮球比赛决赛、开学典礼等也会在体育馆举行");strcpy(G->vexs[8].introduction ,"图书馆高12层,是杭电教学区内最高的建筑物,是热爱学习的同学们的圣地");strcpy(G->vexs[9].introduction ,"社团活动和很多晚会举办的地方");strcpy(G->vexs[10].introduction ,"位于学校教学区的正中央,是杭电的标志性建筑物之一");return G;}
void RudeGraph(MGraph *G,int b,int w,int k,int sum){int p,j,n;if(b==w) {for(p=0;p<k;p++){printf("%d->",G->a[p]);}printf("%d  ",G->a[k]);printf("路线总长:%dkm\n",sum);if(sum<G->minrude){G->r=k;G->minrude=sum;for(p=0;p<=k;p++){G->min[p]=G->a[p];}}return ;}else{for(j=1;j<=10;j++){if(G->arc[b][j]<5000&&G->vexs[j].park==0){k++;G->a[k]=j;sum+=G->arc[b][j];             G->vexs[j].park=1;RudeGraph(G,j,w,k,sum);    //通过递归对所有路径进行深度搜索k--;                       //递归返回这一层后对顶点信息进行重新初始化G->vexs[j].park=0; sum-=G->arc[b][j];}}}return ;
}int main(void)
{int c,i,p,k;MGraph *T;T=CreateGraph();while(1){printf("**********************************\n");printf("欢迎来到******大学景点信息服务系统\n");printf("1.景点信息查询\n");printf("2.路线查询服务\n");printf("3.退出\n");printf("**********************************\n");printf("请选择你要查询的功能:\n");scanf("%d",&c);if(c==1){printf("**********************************\n");printf("******大学共有如下十处景点:\n");for(i=1;i<=10;i++){printf("%d.",T->vexs[i].num);printf("%s:    ",T->vexs[i].name);printf("%s\n",T->vexs[i].introduction);}}else if(c==2){printf("**********************************\n");printf("请输入当前景点编号和你想要去的景点编号:\n");printf("(注:景点编号可在功能1内查询)\n");int b,w;//初始化访问标志for(i=0;i<10;i++){T->vexs[i].park=0;}scanf("%d %d",&b,&w);while(b<1||b>10||w<1||w>10){printf("输入错误,请重新输入:\n");scanf("%d %d",&b,&w);}if(b==w){printf("您已经在此景点,请重新输入:\n");scanf("%d %d",&b,&w);}else{T->a[0]=b;T->vexs[b].park=1;printf("从景点%d到景点%d共有如下路径:\n",b,w);RudeGraph(T,b,w,0,0);printf("最短路径为:\n");for(p=0;p<T->r;p++){printf("%d->",T->min[p]);}printf("%d  ",T->min[T->r]);printf("路线总长:%dkm\n",T->minrude);T->minrude=100;                        //重新初始化最短路径长度}}else if(c==3) break;else printf("输入错误,请重新输入:\n");}printf("祝您生活愉快,再见^v^");return 0;
}

下面提供Dijkstra算法的伪代码:

和深度搜索相比,Dijkstra的代码只是在算法和最后输出时有所不同,在顶点信息中多加了一个变量存储当前顶点的直接前驱节点,其它地方代码段上的注释应该足够明确,当然算法的思想还是需要看代码前提前掌握的。

typedef struct vexsinfo //顶点信息
{int park; //访问的标志int num; //景点的编号int prenum; //记录当前顶点的前一个顶点编号int quanzhi; //顶点的权值char name[32]; //景点的名称char introduction[256]; //景点的介绍
}vexsinfo;typedef struct MGraph
{vexsinfo vexs[50];//顶点表int arc[50][50];//边表int v,e;//定点数和边数
} MGraph;void RudeGraph(MGraph *G,int b,int k){         //迪杰斯特拉求最短路径int i,j,min,minu;min=1000;for(j=1;j<=10;j++){if(G->arc[b][j]<5000&&G->vexs[b].quanzhi+G->arc[b][j]<G->vexs[j].quanzhi&&G->vexs[j].park==0){G->vexs[j].prenum=b;               //更新当前顶点的直接前驱节点G->vexs[j].quanzhi=G->vexs[b].quanzhi+G->arc[b][j];   //对顶点的权值进行更新}}G->vexs[b].park=1;for(i=1;i<=10;i++){                        //找到目前权值最小的点的编号存储minuif(G->vexs[i].quanzhi<min&&i!=b&&G->vexs[i].park==0){min=G->vexs[i].quanzhi;minu=i;}}k++;if(k<10)                       RudeGraph(G,minu,k);                   //对当前权值最小的点进行递归else                         //有个记录前驱编号的还没用到,先求出最短路径再实现输出return ;}

最短路径的输出:

                 //初始化顶点权值for(i=0;i<=10;i++){T->vexs[i].quanzhi=5000;}   T->vexs[b].prenum=-1;           //没有前驱结点将其设为-1T->vexs[b].park=0;T->vexs[b].quanzhi=0;RudeGraph(T,b,1);printf("从景点%d到景点%d最短路径为:\n",b,w);b=w; j=0;while(T->vexs[b].prenum!=-1){      //从终点向前查找前驱节点并保存在数组里a[j]=T->vexs[b].prenum;b=T->vexs[b].prenum;j++;}printf("最短路径为:\n");for(i=j-1;i>=0;i--){             //对数组逆向输出,从而找到最短路径printf("%d->",a[i]); }printf("%d\n",w);printf("路径长度为:\n");printf("%d\n",T->vexs[w].quanzhi);         

————————————————————————————————————————————————————

放一个修改后的迪杰斯特拉的完整代码:

要用的话修改一下CreateGraph()中的G->v和G->e,把对应邻接矩阵改一改就可以了

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define M 5000              //假设两顶点之间没有路径,用5000来表示typedef struct vexsinfo //顶点信息
{int park; //访问的标志int num; //景点的编号int prenum; //记录当前顶点的前一个顶点编号int quanzhi; //顶点的权值char name[32]; //景点的名称char introduction[256]; //景点的介绍
}vexsinfo;typedef struct MGraph
{vexsinfo vexs[50];//顶点表int arc[50][50];//边表int v,e;//定点数和边数
} MGraph;MGraph* CreateGraph()
{MGraph *G;int i,j,k;G=(MGraph*)malloc(sizeof(MGraph));//初始化访问标志for(i=0;i<G->v;i++){G->vexs[i].park=0;}//初始化顶点数目G->v=10;//初始化边的数目G->e=13;//给景点数组编号for(i=1;i<=G->v;i++)G->vexs[i].num=i;for(j=1;j<=G->v;j++)for(k=1;k<=G->v;k++){G->arc[j][k]=M;}//初始化矩阵,赋予每条边权值G->arc[1][2]=G->arc[2][1]=1;G->arc[1][3]=G->arc[3][1]=3;G->arc[1][10]=G->arc[10][1]=8;G->arc[2][6]=G->arc[6][2]=2;G->arc[4][3]=G->arc[3][4]=1;G->arc[4][5]=G->arc[5][4]=1;G->arc[9][5]=G->arc[5][9]=2;G->arc[6][7]=G->arc[7][6]=1;G->arc[7][8]=G->arc[8][7]=2;G->arc[10][7]=G->arc[7][10]=3;G->arc[8][9]=G->arc[9][8]=2;G->arc[8][10]=G->arc[10][8]=2;G->arc[9][10]=G->arc[10][9]=3;//初始化顶点信息strcpy(G->vexs[1].name ,"校  门");strcpy(G->vexs[2].name ,"综合楼");strcpy(G->vexs[3].name ,"科技馆");strcpy(G->vexs[4].name ,"月牙湖");strcpy(G->vexs[5].name ,"咖啡屋");strcpy(G->vexs[6].name ,"篮球场");strcpy(G->vexs[7].name ,"体育馆");strcpy(G->vexs[8].name ,"图书馆");strcpy(G->vexs[9].name ,"学生活动中心");strcpy(G->vexs[10].name ,"三炷香");strcpy(G->vexs[1].introduction ,"曾经是亚洲第一大校门,现因临沂大学重建以后成为亚洲队二大校门");strcpy(G->vexs[2].introduction ,"老师和领导们办公的地方");strcpy(G->vexs[3].introduction ,"里面有学校的校史馆,记录着学校发展的历史");strcpy(G->vexs[4].introduction ,"学校里面唯一的湖,旁边有一片草地,是情侣们经常出没的地方,里面有许多鸭子游来游去");strcpy(G->vexs[5].introduction ,"咖啡屋是学生在运营的,里面每天都会有学生和老师在学习和娱乐");strcpy(G->vexs[6].introduction ,"篮球热爱者的天堂,篮球比赛都在这里举办");strcpy(G->vexs[7].introduction ,"很多明星来开演唱会时会在体育馆内进行,其次篮球比赛决赛、开学典礼等也会在体育馆举行");strcpy(G->vexs[8].introduction ,"图书馆高12层,是教学区内最高的建筑物,是热爱学习的同学们的圣地");strcpy(G->vexs[9].introduction ,"社团活动和很多晚会举办的地方");strcpy(G->vexs[10].introduction ,"位于学校教学区的正中央,是学校的标志性建筑物之一");return G;}void RudeGraph(MGraph *G,int b,int k){         //迪杰斯特拉求最短路径int i,j,min,minu;min=1000;for(j=1;j<=G->v;j++){if(G->arc[b][j]<5000&&G->vexs[b].quanzhi+G->arc[b][j]<G->vexs[j].quanzhi&&G->vexs[j].park==0){G->vexs[j].prenum=b;               //更新当前顶点的直接前驱节点G->vexs[j].quanzhi=G->vexs[b].quanzhi+G->arc[b][j];   //对顶点的权值进行更新}}G->vexs[b].park=1;for(i=1;i<=G->v;i++){                        //找到目前权值最小的点的编号存储minuif(G->vexs[i].quanzhi<min&&i!=b&&G->vexs[i].park==0){min=G->vexs[i].quanzhi;minu=i;}}k++;if(k<G->v)                       RudeGraph(G,minu,k);                   //对当前权值最小的点进行递归else                         //有个记录前驱编号的还没用到,先求出最短路径再实现输出return ;
}int main(void)
{int c,i,p,b,w,j;int a[50];MGraph *T;T=CreateGraph();while(1){printf("**********************************\n");printf("欢迎来到中山大学景点信息服务系统\n");printf("1.景点信息查询\n");printf("2.路线查询服务\n");printf("3.退出\n");printf("**********************************\n");printf("请选择你要查询的功能:\n");scanf("%d",&c);if(c==1){printf("**********************************\n");printf("中山大学共有如下十处景点:\n");for(i=1;i<=T->v;i++){printf("%d.",T->vexs[i].num);printf("%s:    ",T->vexs[i].name);printf("%s\n",T->vexs[i].introduction);}}else if(c==2){printf("**********************************\n");printf("请输入当前景点编号和你想要去的景点编号:\n");printf("(注:景点编号可在功能1内查询)\n");int b,w;//初始化访问标志for(i=0;i<T->v;i++){T->vexs[i].park=0;}//初始化顶点权值for(i=0;i<=32;i++){T->vexs[i].quanzhi=5000;}scanf("%d %d",&b,&w);while(b<1||b>T->v||w<1||w>T->v){printf("输入错误,请重新输入起点和终点:\n");scanf("%d %d",&b,&w);}if(b==w){printf("您已经在此景点,请重新输入:\n");scanf("%d %d",&b,&w);}else{T->vexs[b].prenum=-1;T->vexs[b].park=0;T->vexs[b].quanzhi=0;RudeGraph(T,b,1);printf("从点%d到点%d最短路径为:\n",b,w);b=w;j=0;while(T->vexs[b].prenum!=-1){a[j]=T->vexs[b].prenum;b=T->vexs[b].prenum;j++;}printf("最短路径为:\n");for(i=j-1;i>=0;i--){printf("%d->",a[i]);}printf("%d\n",w);printf("路径长度为:\n");printf("%d\n",T->vexs[w].quanzhi);}}else if(c==3) break;else printf("输入错误,请重新输入:\n");}printf("祝您生活愉快,再见^v^");return 0;
}

———————————————————————————————————————————————————

很多人加我讨论这段程序,总结几个问题吧:

不同编译器之间会有差距,有些人会显示缺少头文件,有些人的最短路径输出不了或者乱码......我是用codeblocks写的,如果大家遇到什么问题建议尝试一下codeblocks进行编译,

再次敲黑板,,,,,,很多人运行的时候可能会少什么头文件或者其他一些bug,建议你们下一个codeblocks试一下,因为我就是用那个IDE写的,不同IDE之间确实会有很大差异,,

如果还解决不了欢迎大家评论里一起交流。

-----------------------------------------------------------------------------------

数据结构—C语言:校园导航系统(最短路径两种算法:深度搜素以及Dijkstra)相关推荐

  1. 非负矩阵分解算法C语言,非负矩阵分解的两种算法

    摘要: 随着计算机和信息技术的发展,矩阵分解成为处理大规模数据的一种有效手段.例如,在数值计算中,利用矩阵分解可将规模较大的复杂问题转化为小规模的简单子问题来求解;在应用统计领域,通过矩阵分解得到原数 ...

  2. 数据结构课设+校园导航系统+西安邮电大学

    数据结构课设+校园导航系统+西安邮电大学 设计目的:在校园建设不断完善的现在,为在校学生提供合适的行走路径,为来访的客人提供各种服务的信息:对于这些问题,可用图结构来表示校园交通网络,编写程序完成校园 ...

  3. C语言判断素数的两种方法

    C语言判断素数的两种方法 素数又称质数.所谓素数是指除了 1 和它本身以外,不能被任何整数整除的数,例如17就是素数,因为它不能被 2~16 的任一整数整除. 思路1):因此判断一个整数m是否是素数, ...

  4. 【❗划重点!C语言函数参数传递只有两种方式(值传递,地址传递),不支持“引用传递”!❗】

    引子 上篇文章<C语言函数传参の结构体数组篇>提到了C语言的函数参数传递方式,百度了一一一大圈,有说两种的,也有说三种的,简直把我搞晕了,"值传递和地址传递"是毫无疑问 ...

  5. 图——最短路径的两种算法

    最短路径 在生活中,例如,当我们坐公交或轻轨时,都会看一下交通图,找到在哪个站下是最快能达到目的地的,也就是路径最小.考虑到交通图的有向性,例如汽车的上山下山.轮船的顺水逆水,所花费的时间或代价就不相 ...

  6. 在.Net framework下遍历XML文挡树的两种算法

    在阅读ASP.NET_XML深入编程技术 (PDF格式)一书的时候,发现遍历树的两种算法:深度优先和广度优先遍历文挡树,前一种需要使用递归,后者则不需要,本人大学时期数据结构学的不好,每每涉及到树,总 ...

  7. 欧拉回路/路径浅谈(七桥问题,两种算法)

    文章目录 前言 引子 欧拉回路/路径 定义 欧拉路径 欧拉回路 无向图(连通) 欧拉回路-无向 欧拉路径-无向 有向图(连通) 欧拉回路-有向 欧拉路径-有向 注意事项 算法 Fluery算法 Hie ...

  8. NILM(非侵入式电力负荷监测)学习笔记 —— 使用NILMTK Toolkit,REDD数据集,CO和FHMM两种算法

    (本文最后,提供整个工程下载) 准备工作 本篇的内容都是基于我前两篇的环境,和数据集进行的. NILM(非侵入式电力负荷监测)学习笔记 -- 准备工作(一)配置环境NILMTK Toolkit NIL ...

  9. 图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS)

    图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS) 阅读本文前,请确保你已经掌握了递归.栈和队列的基本知识,如想掌握搜索的代码实现,请确保你能够用代码实现栈和队列的基本操作. 深度优先遍 ...

最新文章

  1. 三层之抽象工厂加反射实例
  2. 如何在PowerPoint2007制造课件免费ppt模板下载
  3. 【Android】安装时, 先拷so主目录(当前设备相关),再拷so次目录,不重复拷贝 (armeabi/armeabi-v7a) arm-v7不兼容arm-v5
  4. python学习类型转换_Python学习总结5:数据类型及转换
  5. python显示小数点后几位数_python窗口编程-3:数位处理(整数)
  6. 超级计算机适用于科学计算,中国科学院
  7. vue使用element ui实现下拉列表分页的功能!!!
  8. SQL Server的游标
  9. 用fiddler解决跨域访问
  10. js小数运算出现多为小数问题_js小数计算小数点后显示多位小数的实现方法
  11. 精选10款超酷的HTML5/CSS3菜单
  12. Matlab随笔之三维图形绘制
  13. Eclipse中配置mybatis-3-config.dtd
  14. iOS 加粗字体方法 (不改变字体字号只加粗文字)
  15. 大众点评热门餐厅抓取与数据分析
  16. python开发autocad_利用Python自动化操作AutoCAD的实现
  17. 数值计算·第八集:二阶锥规划(CVXPY版)
  18. Structure of Heap
  19. mysql小王 保密_街机斗地主小王搓牌
  20. python3.6安装包下载_Python 3.6.6安装教程(附安装包) | 我爱分享网

热门文章

  1. 产品设计有哪些原则?
  2. 产品运营都必须知道的数据指标们
  3. 迅雷因版权问题不能访问
  4. linux改mac地址目录,Linux下如何修改网卡MAC地址
  5. 可视化学习笔记5-pytorch利用summary()打印神经网络的结构
  6. win10的局域网如何设为专用网络
  7. OpenHarmony在Amlogic A311D芯片平台的快速开发上手指南
  8. SAP UI5 应用开发教程之八十三 - SAP UI5 的自动化测试套件页面的开发步骤介绍试读版
  9. 基于JAVA博物馆交流平台计算机毕业设计源码+系统+lw文档+部署
  10. 小迪教程第三天——access注入片段