Dijkstra图的最短路径算法。
搜索过程中有 一个搜索过的节点 used ,一个 起始点到各点的最短距离distance, 一个前驱节点表 prev 用来标识这个节点在distance存储的距离的前驱节点,最后用于生成最短路径。
1:将 start 放入 used ,从起始点 start 遍历周边节点,将可到达的节点的距离放入 distance ,并将 prev 中的对应节点的前驱设置为 start。
private static void init(boolean[] used, int[] distance, int[] previous, int[][] graph){
for (int i = 0; i < used.length; i++){
used[i] = false;
distance[i] = graph[GraphUtils.FROM][i];
if (graph[GraphUtils.FROM][i] != GraphUtils.MAX){
previous[i] = GraphUtils.FROM;
} else {
previous[i] = -1;
}
}
previous[GraphUtils.FROM] = -1;
used[GraphUtils.FROM] = true;
distance[GraphUtils.FROM] = 0;
}
2:在distance 中选择没有 used 的最短的节点 min。
3:将 min 放入 used 。遍历 used 周边节点 around 的距离 dis ,如果 around 没在used中 并且 distance[min] + dis < distance[around],那么distance[around] = distance[min] + dis,pre[around] = min。
4:循环 2,3 直到没有min
public static void dijkstra(int[][] graph, int to){
int nodeNum = graph.length;
boolean[] used = new boolean[nodeNum];
int[] distance = new int[nodeNum];
int[] previous = new int[nodeNum];
init(used, distance, previous, graph);
LOG.d(distance);
for (int i = 0; i < nodeNum; i++){
int minIndex = GraphUtils.FROM;
int min = GraphUtils.MAX;
for (int j = 0; j < nodeNum; j++){
if ((!used[j]) && distance[j] < min){
minIndex = j;
min = distance[j];
}
}
if (min < GraphUtils.MAX){
used[minIndex] = true;
for (int j = 0; j < nodeNum; j++){
if ((!used[j]) && graph[minIndex][j] != GraphUtils.MAX){
if (distance[minIndex] + graph[minIndex][j] < distance[j]){
distance[j] = distance[minIndex] + graph[minIndex][j];
previous[j] = minIndex;
}
}
}
}
}
LOG.d(used);
LOG.d(previous);
LOG.d(distance);
LOG.d(printLine(getLine(previous, to)));
}
5:在prev中找到目标节点 end,prev[end] <- prev[prev[end]] <- ...... prev[start] 为最短路径。
public static int[] getLine(int[] prev, int to){
int[] roleLine = new int[prev.length];
int i = to;
int j = 0;
roleLine[j++] = to;
while (i >= 0){
roleLine[j++] = prev[i];
i = prev[i];
}
return Arrays.copyOf(roleLine, j);
}
public static String printLine(int[] line){
StringBuffer sb = new StringBuffer();
for (int i = line.length - 2; i >= 0; i--){
sb.append(line[i]);
if (i - 1 >= 0)
sb.append(" -> ");
}
return sb.toString();
}