Floyd算法计算最短距离
思路理解:
虽然K从0开始到n-1,代表的分别是以A,B,C...作为中间节点去计算最短距离
我们以EF两点距离来看,再k=0时,我们选择A点作为中间节点,考虑了d(EF)和d(EA)+d(AF)的大小,并且取较小值更新d(EF)
在k=1时,选择B点作为中间节点,考虑了d(EF)和d(EB)+d(BF)的大小,这个地方要注意的是在第一轮中d(EB)和d(BF)必然已经被比较过一次(EA+AB和BA+AF),
所以,经过第二轮比较,d(EF)已经是所有以A和B作为中间节点的组合中的最小值,这个组合不仅仅是d(EAF)和d(EBF),还包含了d(EABF)和d(EBAF)
那么可以退出当k等于n-1的时候,EF已经尝试了将0~n的节点的所有组合作为中间节点,那么它的长度必然是这些组合中最短的.
import com.google.common.collect.HashBasedTable; import com.google.common.collect.Table; import java.util.Arrays; public class App { //正无穷 public static double infinity = Double.POSITIVE_INFINITY; /** * 计算所有节点最短路径的Floyd算法 * 记住k一定再最外层循环! * * @param graph 图的距离矩阵 */ public static double[][] floyd(double[][] graph) { int N = graph.length; double[][] distance = new double[N][N]; //权重矩阵复制一份给距离矩阵 for (int i = 0; i < N; i++) { System.arraycopy(graph[i], 0, distance[i], 0, graph[i].length); } for (int k = 0; k < N; k++) { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (distance[i][j] > distance[i][k] + distance[k][j]) { distance[i][j] = distance[i][k] + distance[k][j]; } } } } return distance; } /** * 结果打印 * * @param header * @param floyd */ public static void matrixPrint(char[] header, double[][] floyd) { System.out.print(" "); for (char c : header) { System.out.printf("%4s ,", c); } System.out.println(); for (int i = 0; i < floyd.length; i++) { System.out.print(header[i]); System.out.println(Arrays.toString(floyd[i])); } } /** * 一般来说,边比较少,输入边的时候用table是比较方便的 * 但floyd算法的运算用的是二维数组,所以还是需要转化到二维数组 * 因为是无向图,所以一条边属于两个点,因此需要i,j查一次,j,i再查一次 * 实在差不多,赋+∞ * * @param header * @param weightedGraph * @return */ public static double[][] tableToMatrix(char[] header, Table<Character, Character, Double> weightedGraph) { double[][] matrix = new double[header.length][header.length]; for (int i = 0; i < header.length; i++) { for (int j = 0; j < header.length; j++) { char rowKey = header[i]; char columnKey = header[j]; Double weight = weightedGraph.get(rowKey, columnKey); if (weight != null) { matrix[i][j] = weight; } else { Double weight1 = weightedGraph.get(columnKey, rowKey); if (weight1 != null) { matrix[i][j] = weight1; } else { matrix[i][j] = infinity; } } } } return matrix; } public static void main(String[] args) { char[] header = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L'}; Table<Character, Character, Double> weightedGraph = HashBasedTable.create(); weightedGraph.put('A', 'B', 17d); weightedGraph.put('A', 'D', 23d); weightedGraph.put('D', 'B', 42d); weightedGraph.put('C', 'B', 15d); weightedGraph.put('C', 'K', 24d); weightedGraph.put('K', 'L', 22d); weightedGraph.put('L', 'J', 17d); weightedGraph.put('K', 'J', 9d); weightedGraph.put('K', 'F', 11d); weightedGraph.put('C', 'F', 40d); weightedGraph.put('C', 'E', 31d); weightedGraph.put('E', 'H', 68d); weightedGraph.put('G', 'H', 18d); weightedGraph.put('F', 'J', 18d); weightedGraph.put('G', 'D', 12d); weightedGraph.put('J', 'H', 12d); weightedGraph.put('E', 'D', 5d); //自己到自己距离0 for (char c : header) { weightedGraph.put(c, c, 0d); } double[][] matrix = tableToMatrix(header, weightedGraph); matrixPrint(header, matrix); double[][] floyd = floyd(matrix); // matrixPrint(header, floyd); } }