弗洛伊德(Floyd)算法
2016-04-18 20:22
393 查看
简介
罗伯特•弗洛伊德(Robert W.Floyd)计算机科学家,图灵奖得主,前后断言法的创始人,堆排序算法和Floyd-Warshall算法的创始人之一。第一次把“不确定性”概念引入程序,并且在分析理论、程序设计语言的逻辑与语义、自动程序验证、自动程序综合、算法分析以及编译器方面做出了巨大贡献,被授予第十三届图灵奖。Floyd-Warshall算法,中文亦称弗洛伊德算法,是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。
算法流程
弗洛伊德算法的原理是动态规划。假设图G中顶点个数为N,则需要对矩阵S进行N次更新。初始时,矩阵S中顶点a[i][j]的距离为顶点i到顶点j的权值;如果i和j不相邻,则a[i][j]=∞。
接下来开始,对矩阵S进行N次更新。第1次更新时,如果”a[i][j]的距离” > “a[i][0]+a[0][j]”(a[i][0]+a[0][j]表示”i与j之间经过第1个顶点的距离”),则更新a[i][j]为”a[i][0]+a[0][j]”。
同理,第k次更新时,如果”a[i][j]的距离” > “a[i][k]+a[k][j]”,则更新a[i][j]为”a[i][k]+a[k][j]”。
更新N次之后,操作完成!
算法实现(Java)
/** * @description 最短路径之弗洛伊德(Floyd)算法(即求网图G中各顶点i到其余顶点j的最短路径prev[i][j]及带权长度dist[i][j]) * 输入 --> G:无向有权图 * 输出 --> 最短距离数组及长度 * @author GongchuangSu * @since 2016.04.18 * @version v1.0 */ public class Floyd { WeightedGraph G; int vlen; // 顶点个数 int[][] prev; // 前驱顶点数组 int[][] dist; // 最短路径数组 private static int INF = Integer.MAX_VALUE; public void floyd(WeightedGraph G) { this.G = G; vlen = G.size(); prev = new int[vlen][vlen]; dist = new int[vlen][vlen]; // 初始化前驱顶点数组和最短路径数组 for (int i = 0; i < vlen; i++) { for (int j = 0; j < vlen; j++) { dist[i][j] = G.getWeight(i, j); // 顶点i到顶点j的路径长度为i到j的权值 prev[i][j] = j; // 顶点i到顶点j的最短距离是经过顶点j } } // 三重循环,找出所有顶点到所有顶点的最短距离 for (int k = 0; k < vlen; k++) { for (int v = 0; v < vlen; v++) { for (int w = 0; w < vlen; w++) { // 如果经过k顶点的路径比原两点间路径更短,则将当前两点间权值设为更小的一个 int temp = (dist[v][k] == INF || dist[k][w] == INF) ? INF : (dist[v][k] + dist[k][w]); if (dist[v][w] > temp) { dist[v][w] = temp; prev[v][w] = prev[v][k]; } } } } } /** * 功能:打印最短路径数组和前驱顶点数组 */ public void print() { System.out.printf("Floyd:\n"); System.out.printf("最短路径数组:\n"); for (int i = 0; i < vlen; i++) { for (int j = 0; j < vlen; j++) System.out.printf("%2d ", dist[i][j]); System.out.printf("\n"); } System.out.printf("前驱顶点数组:\n"); for (int i = 0; i < vlen; i++) { for (int j = 0; j < vlen; j++) System.out.printf("%d ", prev[i][j]); System.out.printf("\n"); } } /** * 功能:根据起点source和终点target输出最短路径 */ public void getPath(int source, int target) { System.out.printf("(%d,%d)最短路径为:\n", source, target); System.out.printf("%d", target); int k = target; while (prev[k][source] != k) { System.out.printf(" <-- %d", prev[k][source]); k = prev[k][source]; } } }
源代码下载:弗洛伊德(Floyd)算法
时间复杂度
由算法代码中的循环嵌套可得知其算法时间复杂度为O(n3)O(n^3)。相关文章推荐
- Qt添加窗口背景图片、Label图片显示、、Label文字显示
- 缺少ld-musl-armhf.so.1
- 数据结构—文本串加密
- elk之磁盘写入性能
- 【C++】C++对象内存模型简介
- poj 2689 Prime Distance
- ReentrantReadWriteLock理解与实例
- android之LoaderManager原理分析
- 常用html知识汇总
- 迪杰斯特拉(Dijkstra)算法
- papi酱视频因违规遭下线整改,你知道原因吗?
- 发现的一个视频数据集
- hdu 1009 FatMouse' Trade
- 第八周项目1(3)
- acm课程练习2--1002
- Error: Cannot retrieve metalink for repository: epel. Please verify its path and try again
- [LeetCode]LRU Cache
- itertools的使用
- 给台式机设置双屏
- Error: Cannot retrieve metalink for repository: epel. Please verify its path and try again