主要思想:将图中每个顶点Vk依次作为中转顶点,比较每个顶点Vi直接到达其余各个顶点Vj的距离dis[ij]与通过中转顶点Vk再到达其余各个顶点Vj的距离dis[ik]+dis[kj],若dis[ik]+dis[kj] < dis[ij],则将dis[ij]更新为dis[ik]+dis[kj] 。经过三次嵌套循环,可获得任意两个顶点之间的最短路径(而Dijkstra算法只能获得指定顶点到其余顶点的最短路径)。
代码实现:
package DataStructure;
import java.util.ArrayList;
import java.util.Arrays;
public class FloydDemo {
// INT 表示不能直接连通
public static final int INT = Integer.MAX_VALUE;
public static void main(String[] args) {
// 创建图
Graph2 graph = new Graph2(6);
String[] vertexS = {"1", "2", "3", "4", "5", "6"};
for (String vertex : vertexS) {
graph.insertVertex(vertex);
}
int[][] weights = {
{0, 1, 12, INT, INT, INT},
{INT, 0, 9, 3, INT, INT},
{INT, INT, 0, INT, 5, INT},
{INT, INT, 4, 0, 13, 15},
{INT, INT, INT, INT, 0, 4},
{INT, INT, INT, INT, INT, 0}
};
graph.insertEdge(weights);
// for (String[] row : floyd(graph)) {
// for (String value : row) {
// System.out.format("%-22s", value);
// }
// System.out.println();
// }
String[][] paths = floyd(graph);
// 顶点5到顶点6的最短路径:
System.out.println(paths[4][5]); // 5 -> 6 w: 4
// 顶点1到顶点5的最短路径:
System.out.println(paths[0][4]); // 1 -> 2 -> 4 -> 3 -> 5 w: 13
}
public static String[][] floyd(Graph2 graph) {
// 获取图的顶点列表
ArrayList<String> vertex = graph.getVertexList();
// 获取邻接矩阵
int[][] edges = graph.getEdges();
// 拷贝
int[][] edgesCopy = new int[edges.length][edges[0].length];
for (int i = 0; i < edges.length; i++) {
edgesCopy[i] = edges[i].clone();
}
// 创建二维数组保存路径,并初始化
String[][] paths = new String[edges.length][edges[0].length];
for (int i = 0; i < paths.length; i++) {
for (int j = 0; j < paths[i].length; j++) {
paths[i][j] = vertex.get(i) + " -> " + vertex.get(j);
}
}
// 中转顶点
for (int i = 0; i < vertex.size(); i++) {
// 出发顶点
for (int j = 0; j < vertex.size(); j++) {
// 出发顶点与中转顶点相同,跳出本次循环
if (i == j) {
continue;
}
// 终止顶点
for (int k = 0; k < vertex.size(); k++) {
// 出发顶点与终止顶点相同,跳出本次循环
if (j == k) {
continue;
}
// 更新最短路径
if (edgesCopy[j][i] < INT && edgesCopy[i][k] < INT) {
if (edgesCopy[j][i] + edgesCopy[i][k] < edgesCopy[j][k]) {
edgesCopy[j][k] = edgesCopy[j][i] + edgesCopy[i][k];
paths[j][k] = paths[j][i] + paths[i][k].substring(1);
}
}
}
}
}
// 添加每条最短路径对应的距离,不能连通用“∞”表示:
for (int i = 0; i < edgesCopy.length; i++) {
for (int j= 0; j < edgesCopy[i].length; j++) {
paths[i][j] = paths[i][j] + " w: " + (edgesCopy[i][j] == INT ? "∞" : edgesCopy[i][j]);
}
}
return paths;
}
}