Floyd(弗洛伊德)算法

该算法是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权(但不可存在负权回路)的最短路径问题,同时也被用于计算有向图的传递闭包。
时间复杂度为 O(N^3)
空间复杂度为 O(N^2)
Floyd算法蕴涵了动态规划的思想,
简单说:从任意节点i到任意节点j的最短路径存在两种可能

  1. 直接从i到j
  2. i经过若干个节点k到j

所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。

Floyd算法适用于APSP(All Pairs Shortest Paths,多源最短路径),是一种动态规划算法,稠密图效果最佳。此算法简单有效,由于三重循环结构紧凑,对于稠密图,效率要高于Dijkstra算法
优点:容易理解,可以算出任意两个节点之间的最短距离,代码编写简单。
缺点:时间复杂度比较高,不适合计算大量数据。

算法代码如下:

void Floyd(AdjMatrix *G)
{int A[MaxVertices][MaxVertices],path[MaxVertices][MaxVertices];int i,j,k;//初始化for (i=0;i<G->numV;i++){for (j=0;j<G->numV;j++){A[i][j]=G->Edge[i][j];path[i][j]=-1;}}
//三重循环,floyd算法核心for (k=0;k<G->numV;k++){for (i=0;i<G->numV;i++){for (j=0;j<G->numV;j++){if (A[i][j]>A[i][k]+A[k][j]){A[i][j]=A[i][k]+A[k][j];path[i][j]=k;}}}}Dispath(A,path,G->numV);//输出函数
}

输出函数包括两部分

void Ppath(int path[][MaxVertices],int i,int j)
{int k;k=path[i][j];if (k==-1){return;}Ppath(path,i,k);printf("%d->",k);Ppath(path,k,j);
}void Dispath(int A[][MaxVertices],int path[][MaxVertices],int n)
{int i,j;for (i=0;i<n;i++){for (j=0;j<n;j++){if (A[i][j]==INF){if (i!=j){printf("从%d到%d没有路径\n",i,j);}}else{printf("  从%d到%d的最短路径长度为:%d ",i,j,A[i][j]);printf("路径:%d->",i);Ppath(path,i,j);//两点i,j之间还有其他中继结点,则循环套用次函数printf("%d\n",j);}}}
}

具体代码如下:

#include<stdio.h>
#include<stdlib.h>
#define MaxVertices 100 //假设包含100个顶点
#define MaxWeight 32767 //不邻接时为32767,但输出时用 "∞"
#define MAXV 10
#define INF 32767
typedef struct{ //包含权的邻接矩阵的的定义char Vertices[MaxVertices];  //顶点信息的数组int Edge[MaxVertices][MaxVertices]; //边的权信息的数组int numV; //当前的顶点数int numE; //当前的边数
}AdjMatrix;void CreateGraph(AdjMatrix *G) //图的生成函数
{ int n,e,vi,vj,w,i,j;printf("请输入图的顶点数和边数(以空格分隔):");scanf("%d%d",&n,&e);G->numV=n;G->numE=e;for(i=0;i<n;i++) //图的初始化for(j=0;j<n;j++){ if(i==j)G->Edge[i][j]=0;else G->Edge[i][j]=32767;}for(i=0;i<n;i++)for(i=0;i<G->numV;i++) //将顶点存入数组中{ printf("请输入第%d个顶点的信息(整型):",i+1);  // G->adjlist[i].vertex=getchar(); scanf(" %c",&G->Vertices[i]);}printf("\n");for(i=0;i<G->numE;i++){ printf("请输入边的信息i,j,w(以空格分隔):");scanf("%d%d%d",&vi,&vj,&w); //若为不带权值的图,则w输入1//若为带权值的图,则w输入对应权值G->Edge[vi-1][vj-1]=w;//①G->Edge[vj-1][vi-1]=w;//②//无向图具有对称性的规律,通过①②实现//有向图不具备此性质,所以只需要①}
}
void DispGraph(AdjMatrix G) //输出邻接矩阵的信息
{ int i,j;printf("\n输出顶点的信息(整型):\n");for(i=0;i<G.numV;i++)printf("%8c",G.Vertices[i]);printf("\n输出邻接矩阵:\n");printf("\t");for(i=0;i<G.numV;i++)printf("%8c",G.Vertices[i]);for(i=0;i<G.numV;i++){ printf("\n%8d",i+1);for(j=0;j<G.numV;j++){ if(G.Edge[i][j]==32767) //两点之间无连接时权值为默认的32767,但输出时为了方便输出 "∞"printf("%8s", "∞");elseprintf("%8d",G.Edge[i][j]);}printf("\n");   }
}
void Ppath(int path[][MaxVertices],int i,int j)
{int k;k=path[i][j];if (k==-1){return;}Ppath(path,i,k);printf("%d->",k);Ppath(path,k,j);
}void Dispath(int A[][MaxVertices],int path[][MaxVertices],int n)
{int i,j;for (i=0;i<n;i++){for (j=0;j<n;j++){if (A[i][j]==INF){if (i!=j){printf("从%d到%d没有路径\n",i,j);}}else{printf("  从%d到%d的最短路径长度为:%d ",i,j,A[i][j]);printf("路径:%d->",i);Ppath(path,i,j);//两点i,j之间还有其他中继结点,则循环套用次函数printf("%d\n",j);}}}
}
void Floyd(AdjMatrix *G)
{int A[MaxVertices][MaxVertices],path[MaxVertices][MaxVertices];int i,j,k;//初始化for (i=0;i<G->numV;i++){for (j=0;j<G->numV;j++){A[i][j]=G->Edge[i][j];path[i][j]=-1;}}
//三重循环,floyd算法核心for (k=0;k<G->numV;k++){for (i=0;i<G->numV;i++){for (j=0;j<G->numV;j++){if (A[i][j]>A[i][k]+A[k][j]){A[i][j]=A[i][k]+A[k][j];path[i][j]=k;}}}}Dispath(A,path,G->numV);//输出函数
}int main()
{ AdjMatrix G;freopen("1.txt","r",stdin);CreateGraph(&G);Floyd(&G);DispGraph(G);
}

注:由于测试输入数据较多,程序可以采用文件输入
5 7
1
2
3
4
5
1 2 2
1 3 4
1 5 2
2 3 1
2 4 6
3 4 2
4 5 3

全源最短路径之弗洛伊德算法(C语言)相关推荐

  1. 图论-全源最短路径-对比Floyd算法与暴力Dijkstra算法

    题目 输入顶点数N,有向边数M,接下来M行输入格式为u,v,w分别代表两个顶点u,v和两点之间边的权值w.输出全源最短路径 输入样例: 6 8 0 1 1 0 3 4 0 4 4 1 3 2 2 5 ...

  2. 最短路径之迪杰斯特拉(Dijkstra 算法)弗洛伊德算法(C语言完整代码实现)

    写在前面:博主是一位普普通通的19届双非软工在读生,平时最大的爱好就是听听歌,逛逛B站.博主很喜欢的一句话花开堪折直须折,莫待无花空折枝:博主的理解是头一次为人,就应该做自己想做的事,做自己不后悔的事 ...

  3. 动态规划在求解全源最短路径中的应用(JAVA)--Floyd算法

    参考图论算法(二)-最短路径的Dijkstra [ 单源 ] 和Floyd[ 多源 ] 解法(JAVA ) 这种算法也叫Floyd-Warshell算法,虽然和Warshell算法名字相近,算法思想也 ...

  4. Johnson 全源最短路径算法 Java实现

    Johnson 全源最短路径算法 Java实现 算法导入 算法核心 复杂度分析 时间复杂度 空间复杂度 代码实现 参考资料 End 算法导入 在之前的文章中,我们讲述了: 经典入门的Dijkstra算 ...

  5. 弗洛伊德算法c语言path,Floyd算法(弗洛伊德算法)

    算法描述: Floyd算法又称为弗洛伊德算法,插点法,是一种用于寻找给定的加权图中顶点间最短路径的算法.从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归地进行n次更新,即由矩阵D(0)=A,按 ...

  6. 图的单源最短路径:Dijkstra算法实现

    本文介绍的是图的非负权值的单源最短路径问题.问题的提出是,对于有权图D,t提供源点v,要找到从v到其他所有点的最短路径,即单源最短路径问题,在本文中,解决这一问题,是普遍比较熟悉的Dijkstra算法 ...

  7. dijkstra算法PHP,单源最短路径(dijkstra算法)php实现

    做一个医学项目,其中在病例评分时会用到单源最短路径的算法.单源最短路径的dijkstra算法的思路如下: 如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点.那么(Vi ...

  8. matlab结束外循环,求单源最短路径的BellmanFord算法的matlab实现及其优化

    function [minD,path] = BellmanFord(w,start,terminal) %求单源最短路径的Bellman-Ford算法(图论) %调用格式:[minD,path] = ...

  9. 【算法设计与分析】 单源最短路径(贪心算法) Dijkstra

    [算法设计与分析] 单源最短路径(贪心算法) Dijkstra [问题描述] Dijkstra算法解决的是带权重的有向图上单源最短路径问题.所有边的权重都为非负值.设置顶点集合S并不断地作贪心选择来扩 ...

最新文章

  1. Libevent调用
  2. DataView.RowFilter使用
  3. 【BZOJ3172】单词(AC自动机)
  4. 【bzoj3442】学习小组 费用流
  5. 理解 JavaScript 闭包
  6. (王道408考研操作系统)第二章进程管理-第三节4:信号量机制(整型、记录型信号量和P、V操作)
  7. 系统学习深度学习(十一)--dropout,dropconect
  8. matlab三相系统电阻折算,基于MATLAB三相异步电动机调压调速系统方案.doc
  9. linux下载安装自我见解
  10. pyTecplot 学习使用
  11. log4j 2.x版本 日志按天分割,按文件大小分割
  12. 这十本书有望成为第四届橙瓜网络文学奖年度十大玄幻作品!
  13. 智慧工地给工地装上“最强大脑”
  14. 如何恢复因为chrome同步而删除的书签
  15. ecshop支持mysql_ecshop安装不支持MySQL
  16. Kotlin版 极简 干货集中营 APP
  17. ∫e^(-x^2)dx怎么求 ??用的是什么方法??
  18. 攻防世界MISC高手区Avatar
  19. 电影《摔跤吧!爸爸》观后感
  20. Android-Studio与Python环境配置

热门文章

  1. 在一起计时器_古典计时器简介之一 qqtimer
  2. C/C++二叉树前序遍历,中序遍历,后序遍历
  3. dbm和mysql使用场景_mysql基本用法总结
  4. 【PAG组件】-从解码渲染层面对比 PAG 与 lottie
  5. 选择排序--Java
  6. 看门狗性能软件测试,《看门狗:军团》PC版性能测试 不建议光追,优化极差
  7. android q全局夜间模式,安卓Q新功能全局夜间模式,网友:都9102年了,魅族Flyme早就有...
  8. oracle clearing,ORACLE DBA常用命令集锦(2)
  9. MySQL查询语句转postGRE语句_PostgreSQL DBA常用SQL查询语句
  10. c语言题库325,2012年二级C语言笔试模拟325