最短路径算法.docx
- 文档编号:7079088
- 上传时间:2023-01-17
- 格式:DOCX
- 页数:23
- 大小:352.77KB
最短路径算法.docx
《最短路径算法.docx》由会员分享,可在线阅读,更多相关《最短路径算法.docx(23页珍藏版)》请在冰豆网上搜索。
最短路径算法
最短距离算法(Dijkstra)设计与编程实现
所在系(院):
专业:
班级:
学号:
姓名:
绪论
随着知识经济的到来,信息将成为人类社会财富的源泉,网络技术的飞速发展与广泛应用带动了全社会对信息技术的需求,最短路径问题作为许多领域中选择最有问题的基础,在电子导航,交通旅游,城市规划以及电力、通讯等各种管网、管线的布局设计中占有重要地位。
最短路径,顾名思义就是在所有的路径中找到距离最短的路径,而我们所说的最短路径通常不仅仅指地理意义的距离最短,还可以引申到其他的度量,如时间、费用、路线容量等。
相应地,最短路径问题就成为最快路径问题,最低费用问题等,所以我们所说的最短路径也可以看做是最优路径问题。
最短路径问题在交通网络结构的分析,交通运输线路的选择,通讯线路的选择与维护,运输货流的最小成本分析,城市公共交通网络的规划等,都有直接应用的价值。
最短路径问题在实际中还应用于汽车导航系统以及各种应急系统等,这些系统一般要求计算出到出事点的最佳线路,在车辆行驶过程中还需要实时的计算出车辆前方的行驶路线,这就决定了最短路径问题的实现应该是高效的。
最短路径问题一直是计算机学科,运筹学,交通工程学,地理信息学等学科的一个研究热点。
经典的图论与不断发展完善的计算机数据结构及算法的有效结合使得新的最短路径算法不断的涌现。
1定义概览
Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。
主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。
Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。
注意该算法要求图中不存在负权边。
问题描述:
在无向图G=(V,E)中,假设每条边E[i]的长度为w[i],找到由顶点V0到其余各点的最短路径。
(单源最短路径)
2概要设计和数据结构选择
按路径长度递增的顺序产生最短路径。
通过以上对问题的分析和任务的理解,设计出一个大体的模块和程序流程。
2.1程序中涉及到的结构体及子函数:
2.1.1结构体:
本程序设计使用了以下结构体:
structvertex
{intnum;//顶点编号
intdata;//顶点信息
};//顶点类型
typedefstructgraph
{
intn;//图中顶点个数
inte;//图中边的个数
structvertexvexs[MAXVEX];//顶点集合
intedges[MAXVEX][MAXVEX];//边的集合
}AdjMaxix;//图的邻接矩阵类型
2.1.2子函数:
设计本程序需分成几个模块,要用到以下几个子函数:
AdjMaxixcreatmgraph()//通过用户交互产生一个有向图的邻接矩阵;
voiddispmgraph(AdjMaxixadj)//用于输出一个有向图的邻接矩阵;
voidppath(intpath[],inti,intv0);
//选择输出一条最短路径
voidDisPath(intdist[],intpath[],ints[],intn,intv0)
//用path计算最短路径
voidDijkstra(AdjMaxixg,intv0)//Dijkstra算法
voidchange(intnum)//用于替换顶点编号
2.1.3结构图与流程图
结构图如图1
图1结构图
流程图如图2
yes
图2程序流程图
3.详细设计和编码
这里设计用邻接矩阵解决实际生活中城市间往返最短路径问题。
3.1算法思想
把图中顶点集合分成两组,第一组为集合S,存放已求出其最短路径的顶点,第二组为尚未确定最短路径的顶点集合是V-S(用U表示),其中V为网中所有顶点集合。
在这里我们设计一个有向图G=(V,E)为G地区的交通图。
在这个图中,V=(1,2,……,N)代表各个城市。
edges是表示G的邻接矩阵,edges[I][j]表示有向边的权,这里的权值代表城市间距离。
若不存在有向边的权,则edges[I][j]的权为无穷大(可取值为INF=32570)。
设S为一个集合,其中的每个元素表示一个城市,求出从源点(自定义)城市到这些顶点城市的最短距离。
S的初态只包含顶点V0。
数组dist记录从V0到其他各城市当前的最短距离,其初值dist[I]=edges[V0][I]。
从S之外的顶点集合V-S中选出一个城市u。
使dist[w]的值最小。
于是从源点到达u只通过S中的城市,把u加入集合S中调整dist中记录的从源点到V-S中每个城市V的距离:
从原来的dist[v]和dist[w]+edges[w][v]中选择较小的值作为新的dist[v]。
重复上述过程,直到S中包含V中其余顶点的最短路径。
3.1.1算法描述
voidDijkstra(AdjMaxixg,intv0)
{intdist[MAXVEX],path[MAXVEX];
ints[MAXVEX];
intmindis,i,j,u,n=g.n;
for(i=0;i { dist[i]=g.edges[v0][i]; s[i]=0; if(g.edges[v0][i] path[i]=v0; else path[i]=-1; } s[v0]=1;path[v0]=0; for(i=0;i { mindis=INF; u=-1; for(j=0;j if(s[j]==0&&dist[j] { u=j; mindis=dist[j]; } s[u]=1; for(j=0;j if(s[j]==0) if(g.edges[u][j] { dist[j]=dist[u]+g.edges[u][j]; path[j]=u; } 3.2采用邻接矩阵的存储结构 3.2.1基本概念 图的邻接矩阵可以使用一个二维数组存储顶点之间相邻关系的邻接矩阵,和一个具有N个元素的一维数组存储顶点信息,其中下标为i的元素存储顶点Vi的信息。 3.2.2算法描述 voidCreatdl(vexlistGV,adjmatrixGA,intn,inte) { intI,j,k,w; cout<<”输入”< for(I=0;I cin>>GV[I]; for(I=0;I for(j=o;j {if(I==j) GA[I][j]=o; else GA[I][j]=MaxValue; } cout<<”输入”< for(k=1;k<=e;k++) {cin>>I>>j>>w; GA[I][j]=GA[I][j]=w; } } 4.上机调试 对设计实现的回顾讨论和分析;算法的时、空性能分析和改进设想,经验和体会等。 4.1调试中遇到的问题与解决方法 在进行输入输出语句的调试时,系统提示无法识别函数,缺少头文件 出现重大错误,多达数百条错误,着实郁闷了一阵;很多标点符号是在中文输入法状态下输入,造成系统无法识别,改掉后错误消失;如 switch语句,在每条选择语句后,缺少break(),错误; 函数方法使用有误,无法通过;在赋实参时,对于变化的实参只需赋初值,子函数也可以调用子函数; 困惑很久的调用子函数问题,在赋实参时找不到实参;用switch语句进行相关选择代换,成功。 连系实际问题上,int型与char型的替换上不知道用什么函数实现; 4.2设计体会 对C语言的使用不是很熟练,造成自己浪费很多时间在复习C语言,如: 结构体的使用,不能灵活应用do,while(),switch()语句等;调用子函数问题上,子函数之间错综复杂的调用和实参,形参的赋值让自己很是迷惑,三天时间,也许更多时间里,都是在研究怎样调用子函数。 虽然最后基本是完成了教授布置下来的课程设计,但是还是有不尽人意的地方: 结点的插入,删除,路径的实际化最终由于时间问题没能解决,很遗憾。 程序缺乏人性化设计,估计第一次使用本程序的人会很迷茫。 4.3时间空间复杂度的计算 利用Dijkstra算法求解最短路径时,求每一对顶点之间的最短路径的一种方法是反复执行n次Dijkstra算法,每次执行以一个顶点为源点,求得从该顶点到其它各顶点的最短路径;其时间复杂度为O(n3)。 其空间的复杂度为o(n)。 5.测试结果 输入数据: 输入城市数为: 4 输入城市线路为: 4 然后输入城市信息(这里每个数字代表1A地2B地3C地4D地): 输入第一个城市信息: 1 输入第二个城市信息: 2 输入第三个城市信息: 3 输入第四个城市信息: 4 输入第一条线路的起点: 1,终点: 3 线路长度为 56 输入第二条线路的起点: 2,终点: 3 线路长度为 78 输入第三条线路的起点: 1,终点: 2 线路长度为 89 输入第三条线路的起点: 3,终点: 4 线路长度为 99 下面是结果截图: 图3输入所有城市信息 图4输出最短路径 6.参考书目 1徐孝凯数据结构实用教程,清华大学出版社,1999年12月第1版。 2谭浩强《c语言程序设计》,清华大学出版社。 3李春葆数据结构习题与解析,清华大学出版社,2004年2月第2版。 4数据结构-—C++语言描述,人民邮电出版社,2005年三月第1版。 5数据结构(C语言描述),清华大学出版社,2004年十月第1版。 7.附录 /*————————————————————————————-----------*//**/ /*用Dijkstra算法求出有向图中某个源点到其他各顶点的最短路径长度*/ /**/ /*————————————————————————————-----------*/ #include #include #include #include #defineINF32767 #defineMAXVEX100 #defineMAX12 structvertex {intnum;//顶点编号 intdata;//顶点的信息 };//顶点类型 typedefstructgraph { intn; inte;//图中顶点的个数和边的个数 structvertexvexs[MAXVEX];//顶点集合 intedges[MAXVEX][MAXVEX];//边的集合 }AdjMaxix;//图的邻接矩阵类型 AdjMaxixcreatmgraph()//通过用户交互产生一个有向图的邻接矩阵 { inti,j,k,w,n,e; intb,t; AdjMaxixadj; cout<<"输入城市数: ";//对图的所有信息进行逐步输入 cin>>n; while(n>MAX||n<0) { cout<<"城市个数不正确! 请重新输入! "< cin>>n; } cout<<"输入城市线路数: "; cin>>e; adj.n=n; adj.e=e; cout<<"输入城市信息: \n"; for(i=0;i { cout<<"第"< "; cin>>adj.vexs[i].data; adj.vexs[i].num=i; } for(i=0;i for(j=0;j adj.edges[i][j]=0; for(k=0;k { cout<<"第"< "< cout<<"起点: "; cin>>b; cout<<"终点: "; cin>>t; cout<<"线路长度为(Km): "; cin>>w; i=0; while(i =b) i++; if(i>=n) { cout<<"输入的起点城市不存在! \n"; abort(); } j=0; while(j =t) j++; if(j>=n) { cout<<"输入的终点不存在! \n"; abort(); } adj.edges[i][j]=w; } return(adj); } voiddispmgraph(AdjMaxixadj)//用于输出一个有向图的邻接矩阵 { inti,j,n,e; n=adj.n; e=adj.e; cout<<"输出线路的矩阵表示: "< cout<<""; for(i=-1;i printf("%6d",i); printf("\n"); cout< for(i=0;i { printf("%6d",i); for(j=0;j if(adj.edges[i][j]==0) printf("%6s","∞"); else printf("%6d",adj.edges[i][j]); cout< } } voidppath(intpath[],inti,intv0) { intk; k=path[i]; if(k==v0) return; ppath(path,k,v0); printf("%d,",k); } voidDisPath(intdist[],intpath[],ints[],intn,intv0) { inti;//用path计算最短路径 printf("path: ");//输出path值 for(i=0;i printf("%3d",path[i]); printf("\n"); for(i=0;i if(s[i]==1&&i! =v0) { printf("从%d到%d的最短路径为: ",v0,i); printf("%d,",v0); ppath(path,i,v0); printf("%d\n",i); } else printf("从%d到%d不存在路径\n",v0,i); } voidDijkstra(AdjMaxixg,intv0) { intdist[MAXVEX],path[MAXVEX]; ints[MAXVEX]; intmindis,i,j,u,n=g.n; for(i=0;i { dist[i]=g.edges[v0][i];//距离初始化 s[i]=0;//s[]置空 if(g.edges[v0][i] path[i]=v0; else path[i]=-1; } s[v0]=1;path[v0]=0;//源点编号v0放入s中 for(i=0;i { mindis=INF; u=-1; for(j=0;j if(s[j]==0&&dist[j] { u=j; mindis=dist[j]; } s[u]=1;//顶点u加入s中 for(j=0;j if(s[j]==0) if(g.edges[u][j] { dist[j]=dist[u]+g.edges[u][j]; path[j]=u; } } printf("输出最短路径: \n"); DisPath(dist,path,s,n,v0);//输出最短路径 } voidchange(intnum)//选择语句用于替换顶点值,输出名称 { switch(num) {case1: printf("A地");break; case2: printf("B地");break; case3: printf("C地");break; case4: printf("D地");break; case5: printf("E地");break; case6: printf("F地");break; case7: printf("G地");break; case8: printf("H地");break; case9: printf("I地");break; case10: printf("J地");break; case11: printf("K地");break; case12: printf("L地");break; } } voidmain() {inti;charx; do//循环函数,使程序可以循环使用 { printf("下面每个数字代表一个城市,请输入相应的代码,第一个输入的是出发地! \n\n"); printf("1A地2B地3C地4D地5E地6F地\n7G地8H地9I地10J地11K地12L地\n"); AdjMaxixg=creatmgraph(); intn=g.n; dispmgraph(g); Dijkstra(g,0); printf("从出发地到各地最短路程长度如下,若长度为0则表示无法到达或在本地: \n"); for(i=0;i {change(g.vexs[0].data); printf("----->"); change(g.vexs[i].data); printf("%3dKm\n",g.edges[0][i]); } printf("\n\n谢谢使用WOW路径查讯系统,如果想退出请输入'#',任意键继续: "); scanf("%c",&x); printf("\n"); } while(x! ='#');//输入n结束程序 } 1)算法思想: 设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径,就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。 在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。 此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。 2)算法步骤: a.初始时,S只包含源点,即S={v},v的距离为0。 U包含除v外的其他顶点,即: U={其余顶点},若v与U中顶点u有边,则正常有权值,若u不是v的出边邻接点,则权值为∞。 b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。 c.以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。 d.重复步骤b和c直到所有顶点都包含在S中。 执行动画过程如下图 1.3算法代码实现: constintMAXINT=32767; constintMAXNUM=10; intdist[MAXNUM]; intprev[MAXNUM]; intA[MAXUNM][MAXNUM]; voidDijkstra(intv0) { boolS[MAXNUM];//判断是否已存入该点到S集合中 intn=MAXNUM; for(inti=1;i<=n;++i) { dist[i]=A[v0][i]; S[i]=false;//初始都未用过该点 if(dist[i]==MAXINT) prev[i]=-1; else prev[i]=v0; } dist[v0]=0; S[v0]=true; for(inti=2;i<=n;i++) { intmindist=MAXINT; intu=v0; //找出当前未使用的点j的dist[j]最小值 for(intj=1;j<=n;++j) if((! S[j])&&dist[j] { u=j;//u保存当前邻接点中距离最小的点的号码 mindist=dist[j]; } S[u]=true; for(intj=1;j<=n;j++) if((! S[j])
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 路径 算法