实验四-图的最短路径(弗洛伊德算法实现)
实验四图的最短路径弗洛伊德算法实现
数据结构与算法课程实验报告实验四:图的相关算法应用姓名:王连平班级:09信科2班学号:I09630221实验四图的相关算法应用一、实验内容求有向网络中任意两点之间的最短路。
二、实验目的掌握图和网络的定义,掌握图的邻接矩阵、邻接表和十字链表等存储表示。
掌握图的深度和广度遍历算法,掌握求网络的最短路的标号法和floyd算法。
三、问题描述对于下面一张若干个城市以及城市间距离的地图,从地图中所有可能的路径中求出任意两个城市间的最短距离及路径,给出任意两个城市间的最短距离值及途径的各个城市。
四、问题的实现4.1数据结构的抽象数据类型定义和说明1)typedef struct ArcCell{//储存弧信息int Distance;ArcCell *info;//此项用来保存弧信息,,在本实验中没有相关信息要保存}ArcCell,AdjMatrix[ MAX_VERTEX_NUM][ MAX_VERTEX_NUM];typedef struct{//储存顶点信息string vexs[ MAX_VERTEX_NUM];//顶点向量AdjMatrix arcs;//邻接矩阵int vexnum , arcnum;//图的当前顶点数和弧数}MGraph;顶点信息和弧信息都是用来建立一个有向网G2)d[v][w];//G中各对顶点的带权长度若P[v][w][u]为TRUE,则u是从v到w当前求得最短路径上的顶点4.2主要的实现思路首先通过一个函数(CreateDN)建立图的邻接矩阵储存方式,一次输入某条弧的起点,终点,和权值。
通过调用Locate函数来找到该弧在邻接矩阵中的相应位置。
其次运用弗洛伊德算法来求各定点的最短路劲,具体思路为:如果从v到w有弧,则存在一条长度为arcs[v][w]的路径,该路径不一定是最短路径。
考虑路径(v,u,w)是否存在,若存在,比较(v,w)和(v,u,w)的长度,取较短者为从v到w的中间点序号不大于0的最短路径。
弗洛伊德算法求解最短路径
弗洛伊德算法求解最短路径算法的基本思想是采用动态规划的方式,逐步地计算图中所有顶点对之间的最短路径长度。
算法首先初始化一个二维数组D,其中D[i][j]表示从顶点i到顶点j的最短路径长度。
初始时,D[i][j]的值为无穷大,表示顶点i到顶点j没有直接路径。
然后,算法通过逐步更新D数组的值,不断地优化顶点对之间的最短路径。
算法的具体步骤如下:1.初始化D数组:对于图中的每一对顶点i和j,如果i等于j,则置D[i][j]=0,表示顶点到自身的距离为0;否则,如果i和j之间有边存在,则置D[i][j]为边的权重,否则置为无穷大。
2.对于图中的每一个顶点k,依次考虑顶点对(i,j),其中i和j分别表示图中的任意两个顶点。
如果从顶点i先经过顶点k再到达顶点j的路径长度小于当前D[i][j]的值,则更新D[i][j]为新的较短路径长度。
3.对于每一对顶点i和j,以每一个顶点k为中间节点,重复步骤2、这样,在每一次迭代中,D数组会根据当前的顶点k得到更短的路径。
4.根据更新后的D数组,可以得到任意两个顶点之间的最短路径长度。
如果需要获取最短路径上的具体路径,则可以使用一个辅助数组P,其中P[i][j]表示从顶点i到顶点j的最短路径上,从顶点i到顶点j前一个顶点的编号。
通过回溯P数组,可以得到最短路径上的所有顶点。
弗洛伊德算法的时间复杂度为O(n^3),其中n表示图中顶点的个数。
由于要对所有顶点对之间的路径长度进行计算,因此算法的运行时间较长。
然而,该算法适用于复杂图中的最短路径计算,可以得到任意两个顶点之间的最短路径及其长度。
弗洛伊德算法在实际应用中有广泛的应用。
例如,在路由算法中,可以使用弗洛伊德算法来计算网络中所有节点之间的最短路径,并根据计算结果进行路由选择。
此外,弗洛伊德算法也可以应用于交通规划、航空航线优化等领域。
总之,弗洛伊德算法是一种用于求解图中所有顶点对之间最短路径的动态规划算法。
通过逐步更新路径长度的方式,可以得到任意两个顶点之间的最短路径及其长度。
弗洛伊德(Floyd)算法
弗洛伊德(Floyd)算法最短路径问题:从某个顶点出发到达另外⼀个顶点的所经过的边的权重和最⼩的⼀条路径弗洛伊德算法解决最短路径问题1.基本思想(1)计算图中各个顶点之间的最短路径,每⼀个顶点都是出发访问点,所以需要将每⼀个顶点看做被访问顶点,求出从每⼀个顶点到其他顶点的最短路径(2)所有顶点都作为中间节点遍历⼀次,每次遍历将各个顶点经过中间节点到另⼀个节点的距离,与不经过该节点的距离相⽐较,若经过中间节点的距离更⼩,就更新距离表与前驱关系(3)时间复杂度O(n3),所有顶点作为出发点、中间节点、终点,每个顶点都要遍历3次2.步骤(1)设置顶点 a 到顶点 b 的最短路径已知为 L ab,顶点 b 到 c 的最短路径已知为 L bc,顶点 a 到 c 的路径为 L ac,则 a 到 c 的最短路径为:min ( ( L ab + L bc ), L ac ),b 的取值为图中所有顶点,则可获得 a 到 b 的最短路径(2)⾄于 a 到 b 的最短路径 L ab或者 b 到 c 的最短路径 L bc,是以同样的⽅式获得(3)三个点为同⼀顶点时:中间顶点为⾃⾝;三个点是不同顶点时:中间顶点是终点的前驱节点;两个顶点直接连通时:中间节点为出发点代码实现import java.util.Arrays;public class Floyd {//弗洛伊德算法解决最短路径问题public static final int BLOCK = 65535;//表⽰顶点之间不直接连通public static void main(String[] args) {char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};//顶点到⾃⾝距离为0int[][] matrix = {{0, 5, 7, BLOCK, BLOCK, BLOCK, 2},{5, 0, BLOCK, 9, BLOCK, BLOCK, 3},{7, BLOCK, 0, BLOCK, 8, BLOCK, BLOCK},{BLOCK, 9, BLOCK, 0, BLOCK, 4, BLOCK},{BLOCK, BLOCK, 8, BLOCK, 0, 5, 4},{BLOCK, BLOCK, BLOCK, 4, 5, 0, 6},{2, 3, BLOCK, BLOCK, 4, 6, 0}};Graph graph = new Graph(matrix, vertex);graph.floyd();graph.result();}}//带权⽆向图class Graph {public char[] vertex;//存放顶点public int[][] matrix;//保存各个顶点到其它顶点的距离,初始为直接连接的距离,算法计算后为最短距离public int[][] relay;//保存中间结点//构造器public Graph(int[][] matrix, char[] vertex) {this.vertex = vertex;this.matrix = matrix;this.relay = new int[vertex.length][vertex.length];//三个点为同⼀顶点时:中间顶点为⾃⾝;三个点是不同顶点时:中间顶点是终点的前驱节点;两个顶点直接连通时:中间节点为出发点for (int i = 0; i < vertex.length; i++) {Arrays.fill(relay[i], i);//初始中间顶点为⾃⾝}}//显⽰算法结果public void result() {for (int k = 0; k < vertex.length; k++) {for (int i = 0; i < vertex.length; i++) {System.out.println(vertex[k] + " 到 " + vertex[i] +" 最短路径 " + matrix[k][i] +" 中间结点 " + vertex[relay[k][i]]);}System.out.println();}}//弗洛伊德算法public void floyd() {int temp;//保存i到j的距离for (int i = 0; i < matrix.length; i++) {//出发点ifor (int j = 0; j < matrix.length; j++) {//中间顶点jfor (int k = 0; k < matrix.length; k++) {//终点ktemp = matrix[i][j] + matrix[j][k];//求从i出发,经过k,到达j的距离 if (temp < matrix[i][k]) {matrix[i][k] = temp;//更新距离relay[i][k] = relay[j][k];//更新中间顶点}}}}}}。
python数据结构与算法——图的最短路径(Floyd-Warshall算法)
python数据结构与算法——图的最短路径(Floyd-Warshall算法)使⽤Floyd-Warshall算法求图两点之间的最短路径不允许有负权边,时间复杂度⾼,思路简单1# 城市地图(字典的字典)2# 字典的第1个键为起点城市,第2个键为⽬标城市其键值为两个城市间的直接距离3# 将不相连点设为INF,⽅便更新两点之间的最⼩值4 INF = 999995 G = {1:{1:0, 2:2, 3:6, 4:4},6 2:{1:INF, 2:0, 3:3, 4:INF},7 3:{1:7, 2:INF, 3:0, 4:1},8 4:{1:5, 2:INF, 3:12, 4:0}9 }1011# 算法思想:12# 每个顶点都有可能使得两个顶点之间的距离变短13# 当两点之间不允许有第三个点时,这些城市之间的最短路径就是初始路径1415# Floyd-Warshall算法核⼼语句16# 分别在只允许经过某个点k的情况下,更新点和点之间的最短路径17for k in G.keys(): # 不断试图往两点i,j之间添加新的点k,更新最短距离18for i in G.keys():19for j in G[i].keys():20if G[i][j] > G[i][k] + G[k][j]:21 G[i][j] = G[i][k] + G[k][j]222324for i in G.keys():25print G[i].values()结果:[0, 2, 5, 4][9, 0, 3, 4][6, 8, 0, 1][5, 7, 10, 0]。
弗洛伊德算法求解最短路径
弗洛伊德算法求解最短路径算法工作原理如下:1.初始化一个n×n的矩阵D,其中D[i][j]表示从节点i到节点j的最短路径长度。
若两节点之间无直接边相连,则用一个很大的值表示不可达。
2.对矩阵D进行初始化,令D[i][j]=w(i,j),其中w(i,j)表示节点i到j的直接边的权重。
3.对于每对节点i和j,以节点k作为中间节点,更新矩阵D,若存在一条路径经过中间节点k,使得路径长度较之前更短,则更新D[i][j]=D[i][k]+D[k][j]。
4.重复步骤3,直到所有节点的最短路径长度被确定。
5.若存在一个k,使得D[k][k]的值为负数,则表示存在一个含有负权重环的路径,即最短路径的长度没有意义。
迭代的次数为n次,其中n为节点的个数。
每次迭代需要对所有的节点对(i,j)进行检查,以找出所有可能的最短路径。
下面是一个使用弗洛伊德算法求解最短路径的示例:```pythondef floydWarshall(graph):n = len(graph)D = graphfor k in range(n):for i in range(n):for j in range(n):if D[i][j] > D[i][k] + D[k][j]:D[i][j]=D[i][k]+D[k][j]return D#测试INF = float('inf') # 无穷大graph = [[0, 5, INF, 10],[INF,0,3,INF],[INF,INF,0,1],[INF,INF,INF,0]]result = floydWarshall(graph)for row in result:print(row)```在上述示例中,我们通过传入一个图的邻接矩阵作为参数,运行floydWarshall函数来求解最短路径。
其中INF表示不可达的情况。
输出结果为:```[0,5,8,9][inf, 0, 3, 4][inf, inf, 0, 1][inf, inf, inf, 0]```输出的矩阵中,每个元素D[i][j]表示从节点i到节点j的最短路径长度。
弗洛伊德算法最短路径
弗洛伊德算法最短路径嘿,咱们来聊聊弗洛伊德算法最短路径这玩意儿。
你可以把它想象成在一个超级大的迷宫里找最快的出口。
我就拿我上次去旅游找酒店的事儿来说吧。
我们到了一个陌生的城市,那城市的道路就像一团乱麻。
我们要从车站去预订的酒店,这就好比在一个复杂的网络里找从一个点到另一个点的最短路线,这就是弗洛伊德算法要解决的问题啦。
我们站在车站门口,手里拿着地图,那地图上的街道密密麻麻的,交叉路口多得数不清。
就像我们面对的是好多节点和连线组成的图形,每个路口就是一个节点,路就是连线,而我们要找的就是从车站这个“起始节点”到酒店那个“目标节点”的最短路径。
弗洛伊德算法呢,就像是一个聪明的向导。
它会把所有可能的路线都考虑进去,不管是大道还是小路。
比如说,我们可以直接坐某一路公交直达酒店附近,这是一条路;也可以先坐地铁到一个中转站,再换乘公交,这又是一条路;甚至还可以打个车到某个地方,然后步行过去,选择可多了。
算法就会像个耐心的数学家,把这些路线的距离都算一算,然后找出最短的那一条。
我们当时就在讨论走哪条路好。
我朋友说要打车,觉得快。
可我看着地图,觉得也许坐公交转地铁会更划算,距离说不定更短呢。
这时候要是有弗洛伊德算法帮忙就好了。
它会把打车可能遇到堵车的时间、公交的站点停靠时间、地铁的行驶速度这些因素都考虑进去,然后得出一个准确的最短时间路径。
就像在算法里,每一段路都有它的“权重”,也就是长度或者花费的时间之类的。
打车虽然速度快,但可能会因为堵车让这个“权重”变得很大;公交虽然慢,但如果一路顺畅,“权重”可能就还好。
弗洛伊德算法会把这些复杂的情况都分析清楚,就像一个超级大脑。
最后我们还是决定先坐公交,再走一小段路。
嘿,你猜怎么着?还真挺顺利,没花多少时间就到酒店了。
这就有点像弗洛伊德算法成功找到了最短路径一样。
所以说,弗洛伊德算法最短路径这个东西啊,虽然听起来很复杂,但它在生活中其实还挺实用呢,能帮我们在复杂的选择中找到最快到达目标的方法,是不是挺神奇的?这算法就像一把神奇的钥匙,打开了找到最短路径的那扇门。
图的最短路径与最小生成树算法实践
图的最短路径与最小生成树算法实践在计算机科学中,图(Graph)是一种抽象的数据结构,它由节点(Vertex)和边(Edge)组成。
图的最短路径和最小生成树是图算法中的两个重要问题,它们在网络、交通、社交网络等领域有着广泛的应用。
本文将介绍图的最短路径算法和最小生成树算法的实践。
一、图的最短路径算法实践图的最短路径算法用于求解两个节点之间的最短路径,常用的算法有迪杰斯特拉算法(Dijkstra Algorithm)和弗洛伊德算法(Floyd Algorithm)。
(这里可以介绍迪杰斯特拉算法和弗洛伊德算法的思想和流程,注意使用文字和图示来说明)在实际应用中,最短路径算法可以被用于许多场景,比如导航系统中的路径规划、物流配送中的最优路线选择等。
例如,在一座城市中,我们需要规划出从A地到B地的最短路径,可以使用最短路径算法来求解。
二、图的最小生成树算法实践图的最小生成树算法用于找到一个连通图的最小生成树,最常用的算法是普里姆算法(Prim Algorithm)和克鲁斯卡尔算法(Kruskal Algorithm)。
(这里可以介绍普里姆算法和克鲁斯卡尔算法的思想和流程,注意使用文字和图示来说明)最小生成树算法在实际应用中也有很多用途,比如电力系统的最优输电线路规划、通信网络的构建等。
例如,在一个城市的交通网络中,我们希望为每个区域之间建立电缆线路,以便实现高速、稳定的通信,可以使用最小生成树算法来求解。
三、图的最短路径和最小生成树算法在实践中的应用图的最短路径和最小生成树算法在现代社会中有广泛的应用,下面将介绍一些实际应用场景。
1. 路径规划最短路径算法可以用于导航系统中的路径规划。
通过输入起点和终点,最短路径算法可以帮助我们找到从起点到终点的最短路径,以便在导航系统上为驾驶员提供准确的路线指引。
2. 物流配送在物流配送中,最短路径算法可以用于选择最优路线,以节省时间和成本。
通过计算各个配送点之间的距离和路径,可以帮助物流公司规划出最佳配送路线,提高配送效率。
Floyd最短路径算法(参考)
Floyd最短路径算法在图论中经常会遇到这样的问题,在一个有向图里,求出任意两个节点之间的最短距离。
我们在离散数学、数据结构课上都遇到过这个问题,在计算机网络里介绍网络层的时候好像也遇到过这个问题,记不请了... 但是书本上一律采取的是Dijkstra算法,通过Dijkstra算法可以求出单源最短路径,然后逐个节点利用Dijkstra算法就可以了。
不过在这里想换换口味,采取Robert Floyd提出的算法来解决这个问题。
下面让我们先把问题稍微的形式化一下:如果有一个矩阵D=[d(ij)],其中d(ij)>0表示i城市到j城市的距离。
若i与j之间无路可通,那么d(ij)就是无穷大。
又有d(ii)=0。
编写一个程序,通过这个距离矩阵D,把任意两个城市之间的最短与其行径的路径找出来。
我们可以将问题分解,先找出最短的距离,然后在考虑如何找出对应的行进路线。
如何找出最短路径呢,这里还是用到动态规划的知识,对于任何一个城市而言,i到j的最短距离不外乎存在经过i与j之间的k和不经过k两种可能,所以可以令k=1,2,3,...,n(n是城市的数目),在检查d(ij)与d(ik)+d (kj)的值;在此d(ik)与d(kj)分别是目前为止所知道的i到k与k到j的最短距离,因此d(ik)+d(kj)就是i到j经过k的最短距离。
所以,若有d(ij)>d(ik)+d(kj),就表示从i出发经过k再到j的距离要比原来的i到j距离短,自然把i到j的d(ij)重写为d(ik)+d(kj),每当一个k查完了,d(ij)就是目前的i到j的最短距离。
重复这一过程,最后当查完所有的k时,d(ij)里面存放的就是i到j之间的最短距离了。
所以我们就可以用三个for循环把问题搞定了,但是有一个问题需要注意,那就是for循环的嵌套的顺序:我们可能随手就会写出这样的程序,但是仔细考虑的话,会发现是有问题的。
for(int i=0; i<n; i++)for(int j=0; j<n; j++)for(int k=0; k<n; k++)问题出在我们太早的把i-k-j的距离确定下来了,假设一旦找到了i-p-j最短的距离后,i到j就相当处理完了,以后不会在改变了,一旦以后有使i到j的更短的距离时也不能再去更新了,所以结果一定是不对的。
floyd算法求最短路径问题的步骤
floyd算法求最短路径问题的步骤Floyd算法是一种用于求解最短路径问题的动态规划算法。
它能够计算出任意两点之间的最短路径长度,并且可以同时得到最短路径的具体路径。
下面是Floyd算法求解最短路径问题的步骤:
1. 创建一个二维数组dist,用于存储任意两点之间的最短路径长度。
初始化时,将所有的元素设为无穷大(表示不可达),但对角线上的元素设为0。
2. 创建一个二维数组path,用于存储任意两点之间最短路径的中间节点。
初始化时,将所有的元素设为-1。
3. 根据给定的图或者网络,将直接相连的两个节点之间的距离填入`dist`数组中。
如果两个节点之间不存在边,则将距离设为无穷大。
4. 使用三重循环进行计算。
外层循环遍历所有可能的中间节点,中间层循环遍历所有可能的起始节点,内层循环遍历所有可能的目标节点。
如果通过中间节点k可以使得从起始节点i到目标节点j的路径更短,即dist[i][k] + dist[k][j] < dist[i][j],则更新dist[i][j]为新的最短路径长度,并更新path[i][j]为中间节点k。
5. 循环结束后,dist数组中存储的就是任意两点之间的最短路径长度,path数组中存储的是最短路径的中间节点。
6. 如果需要获取具体的最短路径,可以通过回溯path数组来获取。
以起始节点i和目标节点j为例,可以通过不断查找path[i][j],直到找到-1为止,得到最短路径
的节点序列。
以上就是Floyd算法求解最短路径问题的步骤。
该算法的时间复杂度为O(n^3),其中n为节点的数量。
弗洛伊德算法实现
弗洛伊德算法实现
弗洛伊德算法(Floyd Algorithm)是一种用于解决最短路径问题的算法,它是以计算机科学家沃尔夫冈·弗洛伊德(Walter Floyd)的名字命名的。
该算法基于Dijkstra算法的思想,但是在处理多个起点的情况时更加高效。
弗洛伊德算法的基本思路是,对于每个节点,维护一个从该节点出发到其他所有节点的最短距离,以及这些节点的当前位置。
然后,从任意一个起点开始,依次计算到其他所有节点的最短路径,直到计算完整个图。
具体实现步骤如下:
1、初始化起点,并计算从该起点出发到其他所有节点的最短距离,以及这些节点的当前位置。
2、从任意一个起点开始,依次计算到其他所有节点的最短路径,直到计算完整个图。
3、对于每个节点,如果当前位置已经遍历过,则更新从当前位置出发到其他所有节点的最短距离。
4、如果当前位置未遍历过,则将其加入待处理列表中。
5、重复步骤2-4,直到计算完整个图。
弗洛伊德算法的时间复杂度为O(E(logV)),其中E表示边数,V表示节点数。
这是因为在每次迭代中,只需要计算当前位置到其他所有节点的最短距离,而不需要重新计算整
个图的最短路径。
因此,弗洛伊德算法比Dijkstra算法更加高效,尤其是当图中存在多个起点时。
弗洛伊德求最短路径算法
}
void Dispath(Mgraph g,int A[][MAX],int path[][MAX],int n,int i,int j)
{
int s[30];
int l=0;
if(A[i][j]==9999)
{
if(i!=j)
printf("从%d到%d没有路径",i,j);
}
printf("是否修改时间 修改: 1 不修改: 0");
scanf("%d",&i);
if(i==1)
{
scanf("%d",&g.v[q][p].money);
g.v[p][q].time=g.v[q][p].time;
}
printf("是否修改路费 修改: 1 不修改: 0");
{
int i;
printf("具体路程是:\n");
for(i=0;i<l-1;i++)
{
printf("起始:%s 下站:%s\n",[s[i]],[s[i+1]]);
printf("车次: %d 出发时间:%0.2f 到站时间: %0.2f 花费:%d 时间:%d\n",g.v[s[i]][s[i+1]].number,g.v[s[i]][s[i+1]].a[0],g.v[s[i]][s[i+1]].a[1],g.v[s[i]][s[i+1]].money,g.v[s[i]][s[i+1]].time);
数据结构floyd算法求最短路径
数据结构floyd算法求最短路径一、简介Floyd算法是一种用于求解图中任意两点之间最短路径的算法,也称为插点法。
它采用动态规划的思想,通过不断地添加中间节点来逐步求解最短路径。
Floyd算法的时间复杂度为O(n^3),适用于较小规模的图。
二、基本思想Floyd算法通过一个二维数组来存储任意两点之间的最短距离,初始化时,该数组存储的是图中各个节点之间的直接距离。
然后,对于每一个中间节点k,遍历整个二维数组,并更新任意两个节点i和j之间的距离,使得i到j经过k时距离更小。
最终得到的二维数组就是任意两点之间的最短距离。
三、具体实现1. 初始化二维数组D,D[i][j]表示节点i到节点j的直接距离。
2. 三重循环遍历整个二维数组D,在每次循环中将节点k作为中转节点,更新D[i][j]。
3. 更新公式:D[i][j] = min(D[i][j], D[i][k]+D[k][j])。
4. 循环结束后得到的二维数组就是任意两点之间的最短距离。
四、代码实现```void floyd(int n, int D[][MAX]){for(int k=1; k<=n; k++){for(int i=1; i<=n; i++){for(int j=1; j<=n; j++){D[i][j] = min(D[i][j], D[i][k]+D[k][j]);}}}}```五、应用场景Floyd算法适用于较小规模的图,一般用于解决稠密图(边数接近节点数平方)中任意两点之间的最短路径问题。
它可以用于计算城市间的最短路程、网络中的最短路径等。
六、优缺点分析优点:1. 算法思想简单,易于理解和实现。
2. 可以求解任意两点之间的最短路径。
3. 时间复杂度为O(n^3),适用于较小规模的图。
缺点:1. 空间复杂度较高,需要开辟二维数组存储各个节点之间的距离。
2. 对于大规模稀疏图,算法效率较低。
3. 无法处理存在负权回路的图。
迪杰斯特拉、弗洛伊德求最图的最短路径
//点,权值
v--;
printf("%d--<%d>-->",travel[i][v], (m->arcs[ travel[i][v] ][i]).weight);
PrintGraph(&swan);
printf("输入待求最短路径的起点:\n");
scanf("%d",&v0);
if(v0<0 || v0>swan.vexnum)
pain = (int *)malloc(sizeof(int)*(V-2));
remote = (int *)malloc(sizeof(int)*V);
//初始化S集(final) 和 shortpath最短路径
for(v=0; v<V; v++)
{
final[v] = 0;
}
printf("\n\n");
}
else
printf(" 此路不通╮(╯︿╰)╭\n\n");
}
/**
*主函数
*/
int main()
{
void ShortestPathbyDIJ(Graph *m, int v0);
printf("路过的点为:\n");
if(!cold)
{
最短路径之弗洛伊德算法
最短路径之弗洛伊德算法下图左部分是⼀个最简单的3个顶点连通⽹图。
先定义两个数组D[3][3]和P[3][3],D代表顶点到顶点的最短路径权值和的矩阵,P代表对应顶点的最⼩路径的前驱矩阵。
在未分析任何顶点之前,我们将D命名为D-1 ,其实它就是初始的图的邻接矩阵。
将P命名为P-1,初始化为图中所⽰的矩阵。
⾸先,我们来分析,所有的顶点经过v0后到达另⼀顶点的最短距离。
因为只有三个顶点,因此需要查看v1->v0->v2,得到D-1 [1][0] + D-1 [0][2] = 2 + 1 = 3。
D-1 [1][2]表⽰的是v1->v2的权值是5,我们发现D-1 [1][2] > D-1 [1][0] + D-1 [0][2],通俗的讲就是v1->v0->v2⽐直接v1->v2距离还要近。
所以我们就让D-1 [1][2] = D-1 [1][0] + D-1 [0][2],同样的D-1 [2][1] = 3,于是就有了D0 的矩阵。
因为有了变化,所以P矩阵对应的P-1[1][2]和P-1[2][1]也修改为当前中转的顶点v0的下标0,于是就有了P0。
也就是说:--->动态规划乎接下来,其实也就是在D0和P0的基础上,继续处理所有顶点经过v1和v2后到达另⼀顶点的最短路径,得到D1和P1、D2和P2完成所有顶点到所有顶点的最短路径的计算。
⾸先我们针对下图的左⽹图准备两个矩阵D-1和P-1,就是⽹图的邻接矩阵,初设为P[j][j] = j这样的矩阵,它主要⽤来存储路径。
接下来,其实也就是在D0和P0的基础上,继续处理所有顶点经过v1和v2后到达另⼀顶点的最短路径,得到D1和P1、D2和P2完成所有顶点到所有顶点的最短路径的计算。
⾸先我们针对下图的左⽹图准备两个矩阵D-1和P-1,就是⽹图的邻接矩阵,初设为P[j][j] = j这样的矩阵,它主要⽤来存储路径。
具体代码如下:package com.neuedu.algorithm;import java.util.ArrayList;import java.util.List;public class FloydInGraph {private static int INF = Integer.MAX_VALUE;private int[][] dist;//顶点i 到 j的最短路径长度,初值是i到j的边的权重private int[][] path;private List<Integer> result = new ArrayList<Integer>();public static void main(String[] args) {FloydInGraph graph = new FloydInGraph(5);int[][] matrix = {{INF, 30, INF, 10, 50},{INF, INF, 60, INF, INF},{INF, INF, INF, INF, INF},{INF, INF, INF, INF, 30},{50, INF, 40, INF, INF},};int begin=0;int end=4;graph.findCheapestPath(begin,end,matrix);List<Integer> list=graph.result;System.out.println(begin+" to "+end+",the cheapest path is:"); System.out.println(list.toString());System.out.println(graph.dist[begin][end]);}public void findCheapestPath(int begin,int end,int[][] matrix){floyd(matrix);result.add(begin);findPath(begin,end);result.add(end);}public void findPath(int i,int j){// 找到路由节点int k=path[i][j];if(k==-1)return;// 从i到路由节点进⾏递归寻找中间节点findPath(i,k);result.add(k);// 从j到路由节点进⾏递归寻找中间节点findPath(k,j);}public void floyd(int[][] matrix){int size=matrix.length;for(int i=0;i< size;i++){for(int j=0;j< size;j++){path[i][j]=-1;dist[i][j]=matrix[i][j];}}for(int k=0;k< size;k++){for(int i=0;i< size;i++){for(int j=0;j< size;j++){if(dist[i][k]!=INF&&dist[k][j]!=INF&&dist[i][k]+dist[k][j]< dist[i][j]){// 更新i和j两点间的距离dist[i][j]=dist[i][k]+dist[k][j];// 更新i和j两点间的路由信息path[i][j]=k;}}}}}public FloydInGraph(int size){this.path=new int[size][size];this.dist=new int[size][size];}}。
图的最短路径——详谈 Floyd算法 和 Dijkstra算法
if(Chara[i][k] == MAX || Chara[k][j] == MAX) continue;//暂时不通
if(Chara[i][j] > Chara[i][k] + Chara[k][j])
{
//如果经过下标k顶点路径比原两点间路径更短
//将当前两点权值设为更小的那一个
Chara[i][j] = Chara[i][k] + Chara[k][j];
void Dijkstra(int src) //src传入的起点
{
for(int i=0; i<m; i++) //初始化起点到所有点的距离
{
dis[i] = Chara[src][i]; //起始位置到i点的距离
vis[i] = 0;//初始化visit
p[i]=0;
}
dis[src] = 0; //到自身距离为0
我们用一个带权图表示这个铁路系统,权值表示城市之间的铁路里程,于是最短路问题就归结为在带权图中找出顶点x0到其他顶点y且具有最小权的路径。
更一般的最短路问题的提法是:设(D,w)是有正值加权的简单有向图,x0是D中的一个固定顶点,寻找从x0到其他顶点y且具有最小权的有向图。
(2)求图的最短路径算法
求图中两点的最短路径问题,可归结为①源点(起点)固定,终点不确定的两点间最短路径②求图中任意两点间的最短路径。
算法思想
在具体讲Dijkstra之前,我们先来做个对比,Floyd算法是穷举了整张图,得到一张二维表,n个点一共n行,第i行的一系列值就表示表示以i为起点到其他各点的最短路径。单源最短路Dijkstra是源点确定时该源点到其他各点的最短路径。聪明的同学一定发现了,哎,这么说来,假如Dijkstra中的源点为i0,那么我在Floyd的二维表找到第i0行不就解决问题了吗?恭喜你,答对了,就是这样。事实上Floyd中的第i0行就是我们所要求的结果。但是在最开始的两种算法的比较中也提到了Floyd的时间复杂度是n的三次方,他把每一行全都求出来了,而许多实际问题中我们只需要特定的那一行,并且在数据较大的时候,在算法竞赛中非常容易超时,此时就需要用到Dijkstra算法了。(由此可见Dijkstra其实就是Floyd的一种特殊情况,所以笔者想采用从一般到特殊的叙述方式)
如何用FLOYD算法搜出最短路径
如何用FLOYD算法搜出最短路径。
在上一篇论文中我们介绍了比较了FLOYD算法和DIJISTRA算法在该项目中的优劣点,在这篇小论文中我们将讨论如何有FLOYD算法把最短路径搜索出来。
一:FLOYD 算法是如何实现搜索最短路径的:FLOYD 算法又称插点法,它的基本过程如下:首先,把图用邻接距阵G表示出来;如果从V i到Vj有路可达,则G(i,j)=d,d表示该路长度,否则G(i,j)=inf, 最后图可以用如下图来表示。
G =0 2 3 Inf Inf 91 0 4 Inf 4 Inf1 1 0 Inf 10 Inf10 Inf 9 0 Inf Inf7 Inf 2 10 0 41 9 8 4 Inf 0为了搜出最短路径我们还需要一个距阵用来记录所插入点的信息。
这个距阵的D,D(i,j)表示从V(i)到V(j)需要经过的点,初始化D(i,j)=jD =1 2 3 4 5 61 2 3 4 5 61 2 3 4 5 61 2 3 4 5 61 2 3 4 5 6然后把各个顶点插入图中,比较插点后的距离与原来的距离,G(i,j)=min(G(i,j)+G(i,k)+G(k,j)},如果是G(i,j)的值变小,则D(i,j)=k;如在上个图中把V1插入后所得到的结果为G =0 2 3 Inf Inf 91 0 4 Inf 01 1 0 Inf 1010 9 0 Inf7 2 10 0 41 4 Inf 0D =1 2 3 4 5 61 2 3 4 51 2 3 4 51 3 4 51 3 4 5 61 4 5 6这样当我们把各个都加入后我们得到的G为G =0 2 3 10 2 61 02 8 0 41 1 0 9 1 53 3 2 8 0 41 3 4 4 3 0D =1 2 3 6 2 51 2 5 6 5 51 2 3 6 2 51 3 3 4 3 53 3 3 6 5 61 1 1 42 6二:如何搜索出最短路径:在G中包含有两点之间最短道路的信息,而在D中则包含了最短通路径的信息。
最短路径floyd算法
最短路径floyd算法
最短路径floyd算法,是用来求解图中任意两个顶点之间的最短路径的一种算法。
它的思想就是从图中任意一个顶点i到任意一个顶点j的路径都是经过若干个顶点中其中一个顶点k,因此我们可以把任意两个顶点i和j之间的最短路径考虑成是从i到k再到j的一条路径,那么问题就转化成了求所有顶点之间的最短路径。
那么具体的步骤是什么呢?
1. 初始化。
我们需要把图的邻接矩阵A复制一份到另外一个邻接矩阵D中,然后将D矩阵上的对角线元素赋值为0,其他的非连通的元素赋值为“∞”,表示无穷大。
2. 比较。
在接下来的循环中,我们需要比较下一步所经过的点k 对于当前的距离而言是否会缩短路径,如果是则更新矩阵D中的值。
3. 循环。
循环的次数为图中的点数,也就是需要比较n次。
在每一次循环中,我们需要比较D[i][j]和D[i][k]+D[k][j]的大小,如果前者比后者大,说明从i到k然后再到j的路径距离更短,那么我们就将D[i][j]的值更新为D[i][k]+D[k][j]。
4. 输出结果。
最后输出矩阵D中的元素,即为图的任意两点之间的最短路径距离。
需要注意的是,如果图中存在负权回路的话,那么这种算法就失效了。
因为这种算法的前提条件是所有边权均为正数,如果存在负权回路,那么就会导致无限缩小路径距离的情况,算法会一直循环下去而得不到结果。
总之,最短路径floyd算法是一种非常实用的算法,它可以帮助我们在各种情况下求解图中任意两点之间的最短路径。
只需要通过简单的代码实现,就能大大提高我们的工作效率。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构与算法课程实验报告实验四:图的相关算法应用
姓名:王连平
班级:09信科2班
学号:I09630221
实验四图的相关算法应用
一、实验内容
求有向网络中任意两点之间的最短路。
二、实验目的
掌握图和网络的定义,掌握图的邻接矩阵、邻接表和十字链表等存储表示。
掌握图的深度和广度遍历算法,掌握求网络的最短路的标号法和floyd算法。
三、问题描述
对于下面一张若干个城市以及城市间距离的地图,从地图中所有可能的路径中求出任意两个城市间的最短距离及路径,给出任意两个城市间的最短距离值及途径的各个城市。
四、问题的实现
4.1数据结构的抽象数据类型定义和说明
1)
typedef struct ArcCell{//储存弧信息
int Distance;
ArcCell *info;//此项用来保存弧信息,,在本实验中没有相关信息要保存
}ArcCell,AdjMatrix[ MAX_VERTEX_NUM][ MAX_VERTEX_NUM];
typedef struct{//储存顶点信息
string vexs[ MAX_VERTEX_NUM];//顶点向量
AdjMatrix arcs;//邻接矩阵
int vexnum , arcnum;//图的当前顶点数和弧数
}MGraph;
顶点信息和弧信息都是用来建立一个有向网G
2)
d[v][w];//G中各对顶点的带权长度
若P[v][w][u]为TRUE,则u是从v到w当前求得最短路径上的顶点
4.2主要的实现思路
首先通过一个函数(CreateDN)建立图的邻接矩阵储存方式,一次输入某条弧的起点,终点,和权值。
通过调用Locate函数来找到该弧在邻接矩阵中的相应位置。
其次运用弗洛伊德算法来求各定点的最短路劲,具体思路为:如果从v到w有弧,则存在一条长度为arcs[v][w]的路径,该路径不一定是最短路径。
考虑路径(v,u,w)是否存在,若存在,比较(v,w)和(v,u,w)的长度,取较短者为从v到w的中间点序号不大于0的最短路径。
以此类推,每次增加一个点,从而求出任意两点间的最短路径。
这样,经过n次比较后,所求得的必为从v到w的最短路径。
按此方法,可以同时求得任意两点间的最短路径。
五、主要源程序代码(包含程序备注)
#include<iostream>
#include<string>
using namespace std;
#define INfinity 10000//最大值
# define MAX_VERTEX_NUM 10//最大顶点数
typedef struct ArcCell{//储存弧信息
int Distance;
ArcCell *info;
}ArcCell,AdjMatrix[ MAX_VERTEX_NUM][ MAX_VERTEX_NUM];
typedef struct{//储存顶点信息
string vexs[ MAX_VERTEX_NUM];//顶点向量
AdjMatrix arcs;//邻接矩阵
int vexnum , arcnum;//图的当前顶点数和弧数
}MGraph;
int Locate(MGraph &G,string v)
{ int a=0;
for (int i=0;i<G.vexnum;i++)
{
if( G.vexs[i]==v) {
a=i;
break;}
}
return a;
}
void CreateDN(MGraph &G)//采用邻接矩阵表示法,构造有向图G
{ string v1,v2;
cout<<"请依次输入图的顶点数和弧数"<<endl;
cin>>G.vexnum>>G.arcnum;
for (int i=0;i<G.vexnum;i++)
{ cout<<"请按顺序输入地点"<<endl;
cin>>G.vexs[i];
}
for (int i=0;i<G.vexnum;i++)//初始化邻接矩阵;
{ for (int j=0;j<G.vexnum;j++) G.arcs[i][j].Distance=INfinity;}
for (int k=0;k<G.arcnum;k++){
cout<<"请输入某条路径的初始地点V1,终点V2及他们之间的距离W"<<endl; cin>>v1>>v2>>w;
int i=Locate(G,v1);
int j=Locate(G,v2);
G.arcs[i][j].Distance=w;
}
}
void Floyd(MGraph &G)
{ int P[MAX_VERTEX_NUM][MAX_VERTEX_NUM][MAX_VERTEX_NUM];
int d[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
for (int v=0;v<G.vexnum;v++)
{ for (int w=0;w<G.vexnum;w++)
{ d[v][w]=G.arcs[v][w].Distance;
for (int u=0;u<G.vexnum;u++)
{ P[v][w][u]=0;
if (d[v][w]<INfinity)//从v到w有直接路径
{P[v][w][v]=1;P[v][w][w]=1; }
}
}
}
for (int u=0;u<G.vexnum;u++)
{for (int v=0;v<G.vexnum;v++)
{for (int w=0;w<G.vexnum;w++)
{ if (d[v][u]+d[u][w]<d[v][w])//从v经u到w的一条路径更短
{
d[v][w]=d[v][u]+d[u][w];
for (int i=0;i<G.vexnum;i++)
{P[v][w][i]=P[v][u][i]||P[u][w][i];}
}
}
}
}
for (int v=0;v<G.vexnum;v++)
{for (int w=0;w<G.vexnum;w++)
{cout <<"从"<<G.vexs[v]<<"到"<<G.vexs[w]<<"的最短路径为:"<<d[v][w]<<endl;
cout <<"途径城市为:";
for (int u=0;u<G.vexnum;u++)
{ if (P[v][w][u]==1)//P[v][w][u]为,说明u为v到w的最短路劲中的一个顶点
{cout <<G.vexs[u];}
}
cout<<""<<endl;
}
}
}
}
void main()
{MGraph *G;
G=new MGraph;
CreateDN(*G);
Floyd(*G);
}
六、总结
通过本次试验,我对于图的定义及其邻接矩阵储存方式有了进一步的了解。
同时对Flyd算法也有了更深的认识。
特别是用这种方法求求任意两点最短路径的过程比用迪杰斯特算法算n次的形式上更加简单,
时间复杂度为()3n O
,是一个简便的算法。
当然在这次实验没用到图的邻接表和十字链表表示方法,所以
在课后需要花更多的时间去熟悉这两种储存方式,同时也要去了解求网络的最短路的标号法。