Floyd算法求解最短路径问题(完整程序代码)_第1页
Floyd算法求解最短路径问题(完整程序代码)_第2页
Floyd算法求解最短路径问题(完整程序代码)_第3页
Floyd算法求解最短路径问题(完整程序代码)_第4页
Floyd算法求解最短路径问题(完整程序代码)_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、.引言在图论中经常会遇到这样的问题,在一个有向图里求出任意两个节点之间的最短距离。当节点之间的权值是正值的时候,我们可以采用Dijkstra算法,用贪心策略加于解决。但当节点之间的权值有负数的时候,Dijkstra就行不通了,这里介绍另外一种算法Floyd最短路径算法。对于任意图,选择存储结构存储图并实现FLOYD算法求解最短路经。将问题分解,分解为两方面。一是对于任意图的存储问题,第二个是实现FLOYD算法求解最短路经。首先对于图的创建选择合适的存储结构进行存储,对于合适的存储结构可以简化程序。本实验采用邻接矩阵存储。然后是实现FLOYD算法求解最短路经,在FLOYD算法中路径的长度即是图中

2、两定点间边的权值,FLOYD算法要求输出任意两个顶点间的最短路径,而且经过的顶点也要输出。考虑到问题的特殊性,采用一个二维数组和一个三维数组进行存储。二维数组存储最短路径,三维数组存储路径经过的顶点,在进行适当的算法后对这两个数组进行输出即可。通过问题的分解,逐个解决,事先所要求的程序。最短路径算法问题是计算机科学、运筹学、地理信息系统和交通诱导、导航系统等领域研究的一个热点。传统的最短路径算法主要有Floyd算法和Dijkstra算法。Floyd算法用于计算所有结点之间的最短路径。Dijkstra算法则用于计算一个结点到其他所有结点的最短路径。Dijkstra算法是已经证明的能得出最短路径的

3、最优解,但它的效率是一个很大的问题。对于具有n个结点的一个图,计算一个结点到图中其余结点最短路径的算法时间复杂度为O。对于一座大中型城市,地理结点数目可能达到几万个到几十万个,计算最短路径的时间开销将是非常巨大的。本文根据吴一民老师的建议,分析当前存在的各种求最短路径的算法,提出一种新的基于层次图的最短路径算法,即将一个平面图划分若干子图,子图抽象为一个高层图。最短路径的计算首先在高层图中进行,缩小了最短路径的查找范围,降低了最短路径计算的时间开销。由于可以动态计算子图间的阻抗函数,算法可适用于动态交通诱导系统。设计目的1培养学生分析解决问题的能力,掌握java语言的程序设计方法;2通过课程设

4、计实践,训练并提高学生在统筹全局、结构设计、查阅设计资料和计算机编程方面的能力;3提高学生实践论文撰写能力。任务与要求: 理论设计部分以课程设计论文的形式提交,格式必须按照课程设计论文标准格式进行书写和装订; 课程设计报告论文包括要求的作业。第一章 Floyd算法1.1 最短路的定义最短路径问题是图论研究中的一个经典算法,旨在寻找图中两结点之间的最短路径。算法的具体形式包括:确定起点的最短路径问题即已知起始结点,求最短路径问题。在无向图中该问题与确定起点的问题完全等同,在有向图中该问题等同于把所有路经反转的确定起点的问题。确定起点终点的最短路径问题即已知起点和终点求两结点之间的最短路径。求距离

5、最短路径问题求图中所有的最短路径。用于解决最短路径问题的算法被称为最短路径算法。单源最短路 定义:给定一个赋权有向图G =V,E,记G中每一条弧aij=上的权为W=Wij,有给定G中的一个起点s和重点t,设p是G中从s到t的一条路,则定义路径p的权是p中有弧的权之和,记为Wp,即:Wp=又若p*是图G中从s到t的一条路径,且满足Wp*=minWp|p为Vs到Vt的路试中对G的所有从s到t的路p取最小,则称p*为从s到t的最短路,Wp*为s到t的最短距离。在一个图G中,求从s到t的最短路径和最短距离问题就称为最短路径问题。1.2 Floyd的定义与思想1.2.1 Floyd Floyd算法又称为

6、弗洛伊德算法,插点法,是一种用于寻找给定的加权图中顶点间最短路径的算法。1.2.2利用一个三重循环产生一个存储每个结点最短距离的矩阵.弗洛伊德算法仍然使用图的邻接矩阵arcsn+1n+1来存储带权有向图。算法的基本思想是:设置一个n x n的矩阵A,其中除对角线的元素都等于0外,其它元素aij表示顶点i到顶点j的路径长度,K表示运算步骤。开始时,以任意两个顶点之间的有向边的权值作为路径长度,没有有向边时,路径长度为,当K=0时, A ij=arcsij,以后逐步尝试在原路径中加入其它顶点作为中间顶点,如果增加中间顶点后,得到的路径比原来的路径长度减少了,则以此新路径代替原路径,修改矩阵元素。具

7、体做法为: 第一步,让所有边上加入中间顶点1,取Aij与Ai1+A1j中较小的值作Aij的值,完成后得到A,第二步,让所有边上加入中间顶点2,取Aij与Ai2+A2j中较小的值,完成后得到A,如此进行下去,当第n步完成后,得到A,A即为我们所求结果,Aij表示顶点i到顶点j的最短距离。因此,弗洛伊德算法可以描述为: Aij=arcsij; /arcs为图的邻接矩阵 Aij=minA ij,A ik+A kj其中 k=1,2,n定义一个n阶方阵序列: D, D, , D. 其中 D ij = G.arcsij; D ij = min Dij,Dik + Dkj , k = 0,1, n-1 D

8、ij是从顶点vi 到vj , 中间顶点是v0的最短路径的长度, D ij是从顶点vi 到vj , 中间顶点的序号不大于k的最短路径长度, Dij是从顶点vi 到vj 的最短路径长度。1.3 Floyd算法描述通过一个图的权值矩阵求出它的每两点间的最短路径矩阵。a 初始化:Du,v=Au,v b For k:=1 to n For i:=1 to n For j:=1 to n If Di,jDi,k+Dk,j Then DI,j:=DI,k+Dk,j; c 算法结束:D即为所有点对的最短路径矩阵从图的带权邻接矩阵A=a nn开始,递归地进行n次更新,即由矩阵D=A,按一个公式,构造出矩阵D;又

9、用同样地公式由D构造出D;最后又用同样的公式由D构造出矩阵D。矩阵D的i行j 列元素便是i号顶点到j号顶点的最短路径长度,称D为图的距离矩阵,同还可引入一个后继节点矩阵path来记录两点间的最短路径。采用的是松弛技术,对在i和j之间的所有其他点进行一次松弛。所以时间复杂度为O; 其状态转移方程如下: mapi,j:=minmapi,k+mapk,j,mapi,jmapi,j表示i到j的最短距离K是穷举i,j的断点 mapn,n初值应该为0,或者按照题目意思来做。当然,如果这条路没有通的话,还必须特殊处理,比如没有mapi,k这条路1.4 Floyd算法过程在图论中经常会遇到这样的问题,在一个有

10、向图里,求出任意两个节点之间的最短距离。我们在离散数学、数据结构课上都遇到过这个问题,在计算机网络里介绍网络层的时候好像也遇到过这个问题,记不请了. 但是书本上一律采取的是Dijkstra算法,通过Dijkstra算法可以求出单源最短路径,然后逐个节点利用Dijkstra算法就可以了。不过在这里想换换口味,采取Robert Floyd提出的算法来解决这个问题。下面让我们先把问题稍微的形式化一下: 如果有一个矩阵D=d,其中d0表示i城市到j城市的距离。若i与j之间无路可通,那么d就是无穷大。又有d=0。编写一个程序,通过这个距离矩阵D,把任意两个城市之间的最短与其行径的路径找出来。我们可以将问

11、题分解,先找出最短的距离,然后在考虑如何找出对应的行进路线。如何找出最短路径呢,这里还是用到动态规划的知识,对于任何一个城市而言,i到j的最短距离不外乎存在经过i与j之间的k和不经过k两种可能,所以可以令k=1,2,3,.,n,在检查d与d+d的值;在此d与d分别是目前为止所知道的i到k与k到j的最短距离,因此d+d就是i到j经过k的最短距离。所以,若有dd+d,就表示从i出发经过k再到j的距离要比原来的i到j距离短,自然把i到j的d重写为d+d,每当一个k查完了,d就是目前的i到j的最短距离。重复这一过程,最后当查完所有的k时,d里面存放的就是i到j之间的最短距离了。所以我们就可以用三个fo

12、r循环把问题搞定了,但是有一个问题需要注意,那就是for循环的嵌套的顺序:我们可能随手就会写出这样的程序,但是仔细考虑的话,会发现是有问题 forint i=0; i forint j=0; j forint k=0; k 问题出在我们太早的把i-k-j的距离确定下来了,假设一旦找到了i-p-j最短的距离后,i到j就相当处理完了,以后不会在改变了,一旦以后有使i到j的更短的距离时也不能再去更新了,所以结果一定是不对的。所以应当象下面一样来写程序: forint k=0; k forint i=0; i forint j=0; j 这样作的意义在于固定了k,把所有i到j而经过k的距离找出来,然后

13、象开头所提到的那样进行比较和重写,因为k是在最外层的,所以会把所有的i到j都处理完后,才会移动到下一个k,这样就不会有问题了,把图用邻接矩阵G表示出来,如果从Vi到Vj有路可达,则Gi,j=d,d表示该路的长度;否则Gi,j=空值。定义一个矩阵D用来记录所插入点的信息,Di,j表示从Vi到Vj需要经过的点,初始化Di,j=j。把各个顶点插入图中,比较插点后的距离与原来的距离,Gi,j = min,如果Gi,j的值变小,则Di,j=k。在G中包含有两点之间最短道路的信息,而在D中则包含了最短通路径的信息。比如,要寻找从V5到V1的路径。根据D,假如D=3则说明从V5到V1经过V3,路径为V5,V

14、3,V1,如果D=3,说明V5与V3直接相连,如果D=1,说明V3与V1直接相连。1.5 Floyd算法优缺点分析Floyd算法适用于APSP,是一种动态规划算法,稠密图效果最佳,边权可正可负。此算法简单有效,由于三重循环结构紧凑,对于稠密图,效率要高于执行|V|次DijkStra算法。优点:容易理解,可以算出任意两个节点之间的最短距离,代码编写简单;缺点:时间复杂度比较高,不适合计算大量数据。第二章 邻接矩阵2.1 邻接矩阵的定义邻接矩阵Adjacency Matrix:是表示顶点之间相邻关系的矩阵。设G=是一个图,其中V=v1,v2,vn。G的邻接矩阵是一个具有下列性质的n阶方阵:2.2

15、邻接矩阵的特点无向图的邻接矩阵一定是对称的,而有向图的邻接矩阵不一定对称。因此,用邻接矩阵来表示一个具有n个顶点的有向图时需要n2个单元来存储邻接矩阵;对有n个顶点的无向图则只存入上下三角阵中剔除了左上右下对角线上的0元素后剩余的元素,故只需1+2+.+=n/2个单元。无向图邻接矩阵的第i行或第i列非零元素的个数正好是第i个顶点的度。有向图邻接矩阵中第i行非零元素的个数为第i个顶点的出度,第i列非零元素的个数为第i个顶点的入度,第i个顶点的度为第i行与第i列非零元素个数之和。用邻接矩阵表示图,很容易确定图中任意两个顶点是否有边相连。2.3 邻接矩阵的表示方法图的邻接矩阵表示法在图的邻接矩阵表示

16、法中:用邻接矩阵表示顶点间的相邻关系用一个顺序表来存储顶点信息图的邻接矩阵 设G=是具有n个顶点的图,则G的邻接矩阵是具有如下性质的n阶方阵:Ai,j=1 若Vi,Vj或者是E中的边;Ai,j=0 若Vi,Vj或者不是E中的边。若G是网络,则邻接矩阵可定义为:Ai,j=Wij 若Vi,Vj或属于EG AI,j=0或 若Vi,Vj或不属于EG其中:Wij 表示边上的权值; 表示一个计算机允许的、大于所有边上权值的数。 例下面带权图的两种邻接矩阵分别为A 3 和A 4 。邻接矩阵的特点:无向图的邻接矩阵一定是一个对称矩阵。无向图的邻接矩阵的第i行或第i列非零元素或非无穷元素个数为第i个顶点的度Dv

17、i.有向图的邻接矩阵的第i行非零元素或非无穷元素个数为第i个顶点的度OD,第i列非零元素或非无穷元素个数就是第i个顶点的入度IDvi。邻接矩阵表示图,很容易确定图中任意两个顶点之间是否有边相连。容易判断两个顶点之间是否有长度为m的路径相连。邻接矩阵表示法的缺点:邻接矩阵占用的存储单元个数只与图中的结点个数有关,而与边的数目无关。一个n各节点的图,若其边数比n平方少得多,那么邻接矩阵中存在大量的无用的单元。第三章 Floyd算法实例3.1Floyd算法实例现有一张城市地图,图中的顶点为城市,无向边代表两个城市间的连通关系,边上的权代表城市之间的距离。求每个城市的最短距离输入用V表示各个城市,输入

18、顶点Vi与Vj,输出 输出所有可能连接的城市的最短距离。最短路径算法的作用就是在图中找出任意两点间最短距离的途径,比如可以在地图上找出任两个城市之间路程最短的那条路径。有两种算法可以实现,一种是迪杰斯特拉Dijkstra算法,一种是弗洛伊德Floyd算法。弗洛伊德Floyd算法过程:、用Dvw记录每一对顶点的最短距离。、依次扫描每一个点,并以其为基点再遍历所有每一对顶点D的值,看看是否可用过该基点让这对顶点间的距离更小。算法理解:最短距离有三种情况:、两点的直达距离最短。如下图、两点间只通过一个中间点而距离最短。图、两点间用通过两各以上的顶点而距离最短。图对于第一种情况:在初始化的时候就已经找

19、出来了且以后也不会更改到。对于第二种情况:弗洛伊德算法的基本操作就是对于每一对顶点,遍历所有其它顶点,看看可否通过这一个顶点让这对顶点距离更短,也就是遍历了图中所有的三角形算法中对同一个三角形扫描了九次,原则上只用扫描三次即可,但要加入判断,效率更低。对于第三种情况:如下图的五边形,可先找一点比如x,使=2,就变成了四边形问题,再找一点比如y,使=2,可变成三角形问题了v,u,w,也就变成第二种情况了,由此对于n边形也可以一步步转化成四边形三角形问题。这里面不用担心哪个点要先找哪个点要后找,因为找了任一个点都可以使其变成n1边形的问题。第四章 结论通过Floyd算法求解图中顶点的最短路径问题实

20、验,更加深入的了解了数据结构与算法在各个领域的应用。比如图的最短路径问题,衍生为校内导游图,乘客路径问题等等的实际性的日常问题。在该实验的求解过程中,把问题分解为三个部分来解决。首先考虑的是对于任意图的存储问题。在数据结构与算法中,介绍了多种图的存储结构,有邻接矩阵存储,邻接表存储以及十字链表等等存储方法。考虑到本实验要对图进行求解路径,采用邻接矩阵存储。邻接矩阵存储图很容易判断图中两个顶点是否相连。例如,判断Vi和Vj是否相连,只需检查Gij是否等于零,如果该、等于零则不相连。以上是两个顶点是否直接相连的算法。然后是路径问题,对于任意两个顶点,路径也就分为三个情况,即直接相连是最短路径,经过

21、某几个顶点后,经过的路径是最短路径,还有这两个顶点之间没有最短路径。对于直接相连的路径就是最短路径,直接输出即可。例如ab直接相连,且最短路径就是直接路径,路径长度为10,输出a到b的路径就为:ab,路径长度为10。经过某几个定点后的路径是最短路径,用二维数组length先保存最短路径长。若lengthijlengthik+lengthkj则经过k点后i到j得的路径短一些,此时将lengthik+lengthkj赋值给lengthij,用二维数组path记录下经过的点k,这样在循环里对整个路径都进行一边比较,保存下最短路径以及这些路径经过的顶点。对于两点之间没有路径的问题,lengthij一直

22、为最大值,若有路径则同第二步,没有则lengthij一直保持不变。最后待解决的问题就是输出任意两点之间的最短路径,从i到j的最短路径全部保存在length中,要向输出任意两点之间的最短路径长度并不难,但如何输出之间经历过的定点呢?在存入的时候首先存入p是离j最近的一点,然后是离p最近的一点,依次存入,最后一个存入的是离i最近的顶点,所以输出的时候必须倒序输出。采用向前递归算法实现。在3x3循环里,如果lengthij=0或者lengthij=INFINF是自定义的最大值都是没有路径的,lengthij=0此时若i=j,则是定点无路径。若lengthij=INF则i到j没有路径。如果length

23、ij=0但是i!=j,此时说明i到j的最短路径是0,路径是存在的,应该另外考虑这种情况,同下面的输出一致。若以上三种情况都不符合则执行正常的输出操作,输出从i到j经过的顶点,并输出路径长度。通过上述三个步骤,解决了Floyd算法的最短路径问题。参考文献1 朱福喜编著.面向对象与Java程序设计.北京:清华大学出版社,20082 焦永兰主编.管理运筹学.北京:中国铁道出版社,20023 黄国瑜,叶乃菁编著。数据结构。清华大学出版社,20054 朱福喜,唐晓军编著.Java编程技巧与开发实例.北京:清华大学出版生,20045 王昆仑,李红.数据结构与算法.北京:中国铁道出版社,2006.56 侯风

24、巍,杨永田.数据结构要点精细.北京航空航天大学出版社,2006.8附录1 程序流程图:2 程序实现代码:package Example;import java.awt.*;import java.awt.event.*;import java.awt.geom.Ellipse2D; import javax.swing.*; publicclass testpaint extends JFrame implements ActionListenerint length = null; publicvoid Floyd int max =9999; int row = G.length; / 图

25、G的行数 int A = newintrowrow;/ 定义任意两点之间经过的点 intPath = newintrow;/ 记录一条路径 length = newintrowrow; for int i = 0; i / 处理图两点之间的路径for int j = 0; j if Gij = max; / 没有路径的两个点之间的路径为默认最大 if Gij = 0; / 本身的路径长度为0 for int i = 0; i / 初始化为任意两点之间没有路径 for int j = 0; j Aij = -1; for int i = 0; i Pathi = -1; / 假设任意两点之间的没

26、有路径for int m = 0; m for int n = 0; n lengthmn = Gmn; for int u = 0; u for int m = 0; m for int n = 0; n if lengthmu + lengthun lengthmn = lengthmu + lengthun;/ 如果存在更短路径则取更短路径 Amn = u;/ 把经过的点加入 for int i = 0; i / 求出所有的路径 int point = newint1; for int j = 0; j point0 = 0; Pathpoint0+ = i; outputPath; v

27、oid outputPath / 输出i到j的路径的实际代码,point记录一条路径的长度 if return; if Pathpoint0+ = j; else outputPath; outputPath; intshuzu=newint66; Button button=new Button; Label label1 = new Label; Label label2 = new Label; Label label3 = new Label; TextField text1 = new TextField; TextField text2 = new TextField; TextF

28、ield text3 = new TextField;public testpaintsuper;text3.addActionListener;text1.setColumns; /设置text1的大小text2.setColumns; /设置text2的大小text3.setColumns; /设置text3的大小button.addActionListener; setLayoutnew FlowLayout; add; add; add; add; add; add; add; pack; setSize; setVisible;int data = /邻接矩阵 0,3,5,8,9999, 3,0,6,4,11, 5,6,0,2,9999, 8,4,2,0,10, 9999,11,9999,10,0,;for int i = 0; i for int j = i; j if return; Floyd Test=new Floyd; for int i = 0; i for int j = i; j System.out.println从顶点+V+到顶点+V+的最短路是:+Test.len

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论