一、Dijkstra原理简介
Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径。
其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。
有向图和无向图均可求解。话不多说,直接图解。
(A1)示例1:求A到F的最短路径过程详解
//距离矩阵如下
int M=2000;
int[][] weight={
{0,6,3,M,M,M},
{6,0,2,5,M,M},
{3,2,0,3,4,M},
{M,5,3,0,2,3},
{M,M,4,2,0,5},
{M,M,M,3,5,0}
};
先看如下表格解释(A出发到F):
以上表格如果没有完全明白,没关系。以下给出每一步的过程图(A出发到F)。
step1:(初始化)
A | B | C | D | E | F |
shorPath[0] | shorPath[[1]] | shorPath[[2]] | shorPath[[3]] | shorPath[[4]] | shorPath[[5]] |
0 | 6 | 3 | M | M | M |
visited=1 lastNode |
step2:
初始化为以上状态。接下来只需要两步就能完成:
(I)在i未访问中,末节点的shortPath值+该节点到其他未访问节点i的值的和 与 节点i的shortPath比较,如前者小,则shortPath[i]更新成这个小的。
同时更新路线path。(第一次shortPath[0]=0,不变)
(II)在i未访问中,找到shortPath数组中最小的。将其标记为以访问状态visited=1,即C shortPath[2],将该节点记为末节点.
标色表示未访问的节点,可能被更新。
A | B | C | D | E | F |
shorPath[0] | shorPath[[1]] | shorPath[[2]] | shorPath[[3]] | shorPath[[4]] | shorPath[[5]] |
0 | 6 | 3 | M | M | M |
visited=1 | visited=1 lastNode |
step3:
重复step2的过程。
(I)shortPath[2]+weight[2][i](i=1,3,4,5)<shortPath[i] ? 更新shortPath[i] : 不更新
(II)未访问节点B D E F 即索引[1][3][4][5]。最小B。visited[1]=1.
A | B | C | D | E | F |
shorPath[0] | shorPath[[1]] | shorPath[[2]] | shorPath[[3]] | shorPath[[4]] | shorPath[[5]] |
0 | 5(3+2<6) | 3 | 6(3+3) | 7(3+4) | M |
visited=1 | visited=1 | ||||
visited=1 lastNode |
过程如下:
step4:
A | B | C | D | E | F |
shorPath[0] | shorPath[[1]] | shorPath[[2]] | shorPath[[3]] | shorPath[[4]] | shorPath[[5]] |
0 | 5 | 3 | shortPath[[1]]+weight[[1]][[3]]>6( 还是6) | shortPath[[1]]+weight[[1]][[4]] 还是7 | shortPath[[1]]+weight[[1]][[5]] 还是M |
visited=1 | visited=1 | visited=1 | |||
visited=1 lastNode |
step5:
A | B | C | D | E | F |
shorPath[0] | shorPath[[1]] | shorPath[[2]] | shorPath[[3]] | shorPath[[4]] | shorPath[[5]] |
0 | 5 | 3 | 6 | shortPath[[3]]+weight[[3]][[4]] 还是7 | shortPath[[3]]+weight[[3]][[5]]=9 更新为9 |
visited=1 | visited=1 | visited=1 | visited=1 | ||
visited=1 lastNode |
step6:
A | B | C | D | E | F |
shorPath[0] | shorPath[[1]] | shorPath[[2]] | shorPath[[3]] | shorPath[[4]] | shorPath[[5]] |
0 | 5 | 3 | 6 | 7 | shortPath[[4]]+weight[[4]][[5]]=7+5>9 还是为9 |
visited=1 | visited=1 | visited=1 | visited=1 | visited=1 | |
visited=1 lastNode |
最终
A | B | C | D | E | F |
shorPath[0] | shorPath[[1]] | shorPath[[2]] | shorPath[[3]] | shorPath[[4]] | shorPath[[5]] |
0 | 5 | 3 | 6 | 7 | 9 |
visited=1 | visited=1 | visited=1 | visited=1 | visited=1 | visited=1 lastNode |
可知:A–>F最小值:9
(A2)示例1:求A到F的最短路径的java代码
import java.util.Scanner;
/*
* @author WangHongbing 284734261@qq.com *
*/
public class Dijkstra {
/**
*
* @param weight n*n维数组。第i行(i=0,1,...n-1)表示节点i到其他节点的权值
* @param start 起始节点,索引
* @return n维数组,到其他节点的最短路径
*/
public static int[] dijkstra(int[][] weight,int start){
int vertexNum = weight.length; //顶点个数
int[] shortPath=new int[vertexNum]; //保存最短路径值
String[] path = new String[vertexNum]; //具体路径存在字符串中
int[] visited = new int[vertexNum]; //顶点i是否已经求过
//初始化
shortPath[start]=0;
visited[start]=1;
int M=2000; //将2000当成无穷大
//初始化shortPath数组
shortPath[start]=0;
path[start]=start+"";
for(int i=0;i<shortPath.length;i++){
if(i!=start){
shortPath[i]=M;
}
}
int lastNode=start;
for(int count=1;count<vertexNum;count++){
//第一次,weight[0][1],weight[0][2],weight[0][3],..weight[0][5]中取最小的
int dmin = Integer.MAX_VALUE;
int k=0;
for(int i=0;i<vertexNum;i++){
if(visited[i]==0 && shortPath[lastNode]+weight[lastNode][i]<shortPath[i]){
//拿lastNode到i的值+之前shortPath中lastNode的值 和 对应shortPath比较。小则更新路线
//然后再找到一个最小的作为最后的节点
shortPath[i]=shortPath[lastNode]+weight[lastNode][i];
//路线更新存在path数组中
path[i]=path[lastNode]+"-->"+i;
}
if(visited[i]==0 && shortPath[i]<dmin){
dmin=shortPath[i];
k=i;
}
}
lastNode=k;
visited[k]=1;
}
System.out.println(path[path.length-1]);
return shortPath;
}
public static void main(String[] args) {
int M=2000;
int[][] weight={
{0,10,M,30,100},
{M,0,50,M,M},
{M,M,0,M,10},
{M,M,20,0,60},
{M,M,M,M,0}
};
int[][] weight2={
{0,6,3,M,M,M},
{6,0,2,5,M,M},
{3,2,0,3,4,M},
{M,5,3,0,2,3},
{M,M,4,2,0,5},
{M,M,M,3,5,0}
};
int[] shortPath = dijkstra(weight2, 0);
System.out.println(shortPath[shortPath.length-1]);
}
}
----------
//weight2输出
0-->2-->3-->5
9