实验四-图的最短路径(弗洛伊德算法实现)
实验四图的最短路径弗洛伊德算法实现

数据结构与算法课程实验报告实验四:图的相关算法应用姓名:王连平班级: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的更短的距离时也不能再去更新了,所以结果一定是不对的。
- 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
,是一个简便的算法。
当然在这次实验没用到图的邻接表和十字链表表示方法,所以
在课后需要花更多的时间去熟悉这两种储存方式,同时也要去了解求网络的最短路的标号法。