最短路算法的求解,都是基于下列事实:节点A到节点B的最短路径有两种可能,一种是直接从A到B,另一种是从A经过若干个节点到B。
Dijkstra算法:单源最短路径问题,时间复杂度为O(n^2);不能处理权值为负的边;
Floyd算法:求解图中任意节点之间的最短路径,时间复杂度为O(n^3);可以处理任意数值权重的边。
程序(朴素版本)
Dijkstra算法
public class Dijkstra {
public int[] getShortestPath(int[][] adjacencyMatrix) {
if (adjacencyMatrix == null || adjacencyMatrix.length == 0
|| adjacencyMatrix[0].length == 0) {
return null;
}
int n = adjacencyMatrix.length;
boolean[] visited = new boolean[n];
int[] shortestPath = new int[n];
visited[0] = true;
int lastNodes = n - 1;
// initialize
for (int i = 0; i < n; i++) {
shortestPath[i] = adjacencyMatrix[0][i];
}
while (lastNodes > 0) {
int shortest = Integer.MAX_VALUE;
int idx = 0;
for (int i = 1; i < n; i++) {
if (visited[i]) {
continue;
}
if (shortestPath[i] < shortest) {
// choose the nearby node
shortest = shortestPath[i];
idx = i;
}
}
visited[idx] = true;
// update shortest path
for (int i = 1; i < n; i++) {
if (visited[i] || adjacencyMatrix[idx][i] == Integer.MAX_VALUE) {
continue;
}
shortestPath[i] = Math.min(shortestPath[i], shortestPath[idx]
+ adjacencyMatrix[idx][i]);
}
--lastNodes;
}
return shortestPath;
}
}
Floyd算法
经典的三层for循环结构,
public class Floyd {
public int[][] getShortestMatrix(int[][] adj) {
if (adj == null || adj.length == 0 || adj[0].length == 0) {
return null;
}
int n = adj.length;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
if (adj[i][k] == Integer.MAX_VALUE
|| adj[j][k] == Integer.MAX_VALUE) {
continue;
}
if (adj[i][k] + adj[j][k] < adj[i][j]) {
adj[i][j] = adj[i][k] + adj[j][k];
}
}
}
}
return adj;
}
}