最短路算法的求解,都是基于下列事实:节点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; } }