JAVA实现Dijkstra算法
本题以此有向图为例
算法思想:
假设有两个顶点集合S和T,集合S中存放图中已找到最短路径的顶点,集合T中存放图中剩余顶点。初始状态时,集合S中只包含源点V0,然后不断从集合T中选取到顶点V0路径长度最短的顶点Vu并入到集合S中。集合S每并入一个新的顶点Vu,都要修改顶点V0到集合T中顶点的最短路径长度值。不断重复此过程,直到集合T中的顶点全部并入集合S中为止,循环结束。
算法主要思路:
1,把有向图转换为邻接表,用任意比较大的正整数表示正无穷大。
2,引入3个辅助数组dist[]、path_data[],set_data[]。
dist[Vi]表示当前已经找到的V0到每个终点Vi的最短路径长度。初始状态:若从V0到Vi有边,则dist[i]为边上的权值,则dist[Vi]为正无穷大。
path_data[Vi]中保存从V0到Vi最短路径上Vi的前一个顶点,假设最短路径上的顶点序列为V0,V1…Vi-1,Vi,则path_data[Vi]=Vi-1。初始状态:如果V0到Vi有边,则path_data[Vi]=V0,否则path[Vi]=-1。
set_data[]为标记数组,set_data[Vi]=0表示Vi在T中,没有被并入最短路径;set_data[Vi]=1,表示Vi在S中,已经并入最短路径。set_data[V0]=1,其余元素全为0。
3,算法执行过程:
从当前dist[]选出最小值,假设最小值为dist[Vu],将set_data[Vu]设置为1,表示并入新的顶点Vu。
循环扫描图中的顶点,对每个顶点进行一下检测:
假设当前顶点为Vj,检测Vj是否已经并入S中,就是看是否set_data[Vj]=1。如果set[Vj]=1,就什么都不做;如果set_data[Vj]=0;则比较dist[Vj]和dist[Vu]+W的大小,W为边<Vu,Vj>的权值。这个比较就是看V0经过旧的最短路径到达Vj和V0经过含有Vu的新的最短路径到达Vj哪个更短。如果dist[Vj]>dist[Vu]+W,则用新的路径更新旧的,并把顶点Vu加入路径中,作为路径上Vj之前的那个顶点,否则什么否不做。
代码如下
package djstl;
public class Djstl {
public static void Dijkstra(int [][] graph, int init_node, int MIN) {
int len = graph[0].length;
int index_setData = 0;
int dist[] = new int[len];
int set_data[] = new int[len];
int path_data[] = new int[len];
int min = MIN;
// 数据初始化
for (int i = 0; i < len; i++) {
dist[i] = graph[init_node][i];
if (i == init_node) {
set_data[i] = 1;
} else {
set_data[i] = 0;
}
if (graph[init_node][i] <1000) {
path_data[i] = init_node;
} else {
path_data[i] = -1;
}
}
path_data[init_node]=-1;// 初始化结束
//关键操作开始
for (int i = 0; i < graph.length; i++) {
min=MIN;
for (int j = 0; j < graph.length; j++) {
if (set_data[j] == 0 && dist[j] <min) {
index_setData = j;
min = dist[j];
}
}
set_data[index_setData] = 1;
//算法主要思路的第三步的实现
for (int k = 0; k < graph.length; k++) {
if (set_data[k] == 0 && (min + graph[index_setData][k])<dist[k]) {
path_data[k] = index_setData;
dist[k] = min + graph[index_setData][k];
}
}
}
for (int i = 1; i < graph.length; i++) {
System.out.println("最短路径前一个结点:"+path_data[i]+"-->"+i+",长度为:"+dist[i]);
}
}
}
下面对方法进行测试:
package djstl;
public class test {
public static void main(String[] args) {
int N = 1000;
int M = 0;
int init_node=0;
int[][] graph = {
{ M, 4, 6, 6, N, N, N },
{ N, M, 1, N, 7, N, N },
{ N, N, M, N, 6, 4, N },
{ N, N, 2, M, N, 5, N },
{ N, N, N, N, M, N, 6 },
{ N, N, N, N, 1, M, 8 },
{ N, N, N, N, N, N, M } };
Djstl.Dijkstra(graph, init_node,N);
}
}
输出结果: