弗洛伊德算法 | 字数总计: 1.4k | 阅读时长: 5分钟 | 阅读量: |
弗洛伊德算法 应用场景-最短路径问题
胜利乡有7个村庄(A, B, C, D, E, F, G)
各个村庄的距离用边线表示(权) ,比如 A – B 距离 5公里
问:如何计算出各村庄到 其它各村庄 的最短距离?
弗洛伊德算法基本介绍
和Dijkstra算法一样,弗洛伊德(Floyd)算法也是一种用于寻找给定的加权图中顶点间最短路径的算法。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。
弗洛伊德算法(Floyd)计算图中各个顶点之间的最短路径 。
迪杰斯特拉算法用于计算图中某一个顶点到其他顶点的最短路径 。
弗洛伊德算法 VS 迪杰斯特拉算法:迪杰斯特拉算法通过选定的被访问顶点,求出从出发访问顶点到其他顶点的最短路径;弗洛伊德算法中每一个顶点都是出发访问点,所以需要将每一个顶点看做被访问顶点,求出从每一个顶点到其他顶点的最短路径。
基本思想:
弗洛伊德算法定义了两个二维矩阵:
矩阵D记录顶点间的最小路径 例如D[0] [3]= 10,说明顶点 0 到 3 的最短路径为10;
矩阵P记录顶点间最小路径中的中转点 例如P[0] [3]= 1,说明顶点 0 到 3的最短路径轨迹为:0 -> 1 -> 3。
它通过3重循环,k为中转点,v为起点,w为终点,循环比较D[v] [w] 和 D[v] [k]+ D[k] [w]最小值,如果 D[v] [k]+ D[k] [w]为更小值,则把 D[v] [k]+ D[k] [w]覆盖保存在D[v] [w] 中。
至于 v 到 k 的最短路径或者 k 到 w 的最短路径也是以同样的方式获得。
图解思路如下:
最短路径问题的代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 package com.nanzx.floyd;import java.util.Arrays;public class FloydAlgorithm { public static void main (String[] args) { char [] vertex = { 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' }; int [][] matrix = new int [vertex.length][vertex.length]; final int N = 65535 ; matrix[0 ] = new int [] { 0 , 5 , 7 , N, N, N, 2 }; matrix[1 ] = new int [] { 5 , 0 , N, 9 , N, N, 3 }; matrix[2 ] = new int [] { 7 , N, 0 , N, 8 , N, N }; matrix[3 ] = new int [] { N, 9 , N, 0 , N, 4 , N }; matrix[4 ] = new int [] { N, N, 8 , N, 0 , 5 , 4 }; matrix[5 ] = new int [] { N, N, N, 4 , 5 , 0 , 6 }; matrix[6 ] = new int [] { 2 , 3 , N, N, 4 , 6 , 0 }; Graph graph = new Graph (matrix, vertex); graph.floyd(); graph.show(); } } class Graph { private char [] vertex; private int [][] dis; private int [][] relay; public Graph (int [][] matrix, char [] vertex) { this .vertex = vertex; this .dis = matrix; this .relay = new int [vertex.length][vertex.length]; for (int i = 0 ; i < vertex.length; i++) { Arrays.fill(relay[i], i); } } public void floyd () { for (int i = 0 ; i < dis.length; i++) { for (int j = 0 ; j < dis.length; j++) { for (int k = 0 ; k < dis.length; k++) { if (dis[j][i] + dis[i][k] < dis[j][k]) { dis[j][k] = dis[j][i] + dis[i][k]; relay[j][k] = relay[i][k]; } } } } } public void show () { for (int k = 0 ; k < dis.length; k++) { for (int i = 0 ; i < dis.length; i++) { System.out.print(vertex[relay[k][i]] + " " ); } for (int i = 0 ; i < dis.length; i++) { System.out.print("(" + vertex[k] + "到" + vertex[i] + "的最短路径是" + dis[k][i] + ") " ); } System.out.println(); System.out.println(); } } }
运行结果:
A A A F G G A (A到A的最短路径是0) (A到B的最短路径是5) (A到C的最短路径是7) (A到D的最短路径是12) (A到E的最短路径是6) (A到F的最短路径是8) (A到G的最短路径是2)
B B A B G G B (B到A的最短路径是5) (B到B的最短路径是0) (B到C的最短路径是12) (B到D的最短路径是9) (B到E的最短路径是7) (B到F的最短路径是9) (B到G的最短路径是3)
C A C F C E A (C到A的最短路径是7) (C到B的最短路径是12) (C到C的最短路径是0) (C到D的最短路径是17) (C到E的最短路径是8) (C到F的最短路径是13) (C到G的最短路径是9)
G D E D F D F (D到A的最短路径是12) (D到B的最短路径是9) (D到C的最短路径是17) (D到D的最短路径是0) (D到E的最短路径是9) (D到F的最短路径是4) (D到G的最短路径是10)
G G E F E E E (E到A的最短路径是6) (E到B的最短路径是7) (E到C的最短路径是8) (E到D的最短路径是9) (E到E的最短路径是0) (E到F的最短路径是5) (E到G的最短路径是4)
G G E F F F F (F到A的最短路径是8) (F到B的最短路径是9) (F到C的最短路径是13) (F到D的最短路径是4) (F到E的最短路径是5) (F到F的最短路径是0) (F到G的最短路径是6)
G G A F G G G (G到A的最短路径是2) (G到B的最短路径是3) (G到C的最短路径是9) (G到D的最短路径是10) (G到E的最短路径是4) (G到F的最短路径是6) (G到G的最短路径是0)