迪杰斯特拉算法
算法思想:
路段权值非负(一般都能满足),通过遍历各路段的路阻(权值),获取起点到其他各个点的最短路径长度。N个点需迭代N-1次。注意事项看代码:
所使用的网络图如图:
import java.util.Arrays;
public class Test1 {
public static void main(String[] args) {
//这里为用户输入网络图的权值矩阵,本质就是各路段的路阻在此处进行表示
int MAX=Integer.MAX_VALUE;//无法到达时使用这个int最大值表示
int[][] weight={
{0,1,12,MAX,MAX,MAX},
{MAX,0,9,3,MAX,MAX},
{MAX,MAX,0,MAX,5,MAX},
{MAX,MAX,4,0,13,15},
{MAX,MAX,MAX,MAX,0,4},
{MAX,MAX,MAX,MAX,MAX,0}
};//行号代表着起点,列号代表着终点
//接下来就是选择出发点,并给出一个函数算出这个起点到其他各点的最短距离
int start=0;//0可以作起点是因为,我们后续将0视作下标
System.out.println(Arrays.deepToString(func(weight,start)));
}
private static int[][] func(int[][] weight,int start){
//进行迪杰斯特拉算法
boolean visit[]=new boolean[weight.length];//用以标记每个点是否被访问过
int[] res=new int[weight.length];//用以记录起点到每一个点的最短距离
int route[]=new int[weight.length];//用以记录最短路径的路线怎么走
route[0]=start;//起点必定是start了
int[][] answer=new int[2][weight.length];
//初始化起点到每个点的距离
for(int i=0;i<weight.length;i++){
res[i]=weight[start][i];
}
//接下来就是在其他点中进行遍历,每次迭代确定一个点纳入最短路径
for(int i=1;i<weight.length;i++){//从1开始只是表明迭代n-1次就可以得到最短路径了!
int min=Integer.MAX_VALUE;
int p=0;//这个随意,用以记录即将纳入最短路径的点的下标
//下面是对未标记点到出发点(不一定就是起点)的最短距离,找到了这个点后,将其设为true(已标记)
for(int j=0;j<weight.length;j++){
if(j!=start&&!visit[j]&&res[j]<min){//因为起点自始至终都没有设为true(中间的逻辑判断不包含第一个逻辑),所以要设一条点不能为起点
p=j;
min=res[j];//这个的含义是什么?意思就是找最小啊!没这个就不对!
}
}
visit[p]=true;
route[i]=p;//新纳入的点将记录至当前路线数组中
//基于上述刚纳入最短路径的点,去以这个点为出发点作路径长度更新(因为最短路径此时就是必经过p点)
for(int j=0;j<weight.length;j++){
if(j==p||weight[p][j]==Integer.MAX_VALUE){
continue;
}
if(res[p]+weight[p][j]<res[j]){
res[j]=res[p]+weight[p][j];
}
}
}
answer[0]=route;//结果数组第一行给出最短路径的路线
answer[1]=res;//结果数组的第二行给出起点到各个点的最短路径长度
return answer;
}
}
给出的结果:
含义为:路线:0->1->3->2->4->5为0-5的最短路径走法,如果指定的OD对不一样,可以调整weight数组使两者处于数组首尾行列即可。answer数组的第二个元素给出的是起点到各个点的最短距离!最后一个元素就是OD对之间的最短路径长度了!
总结🏝
-
上述代码的目的是:找出一个网络图中指定起点到其余各个点的最短距离。route已给出最短路径对应的路线(注意是从0下标开始走)。
-
代码主要功能体现在func()函数:对其进行实现的话,可概括为以下几个步骤:
a.定义标记数组和距离记录数组,并对其进行初始化
b.迭代N-1次遍历完除起点外的所有其他的点
c.针对上述每一次的遍历要做两件事:
①:点更新:通过是否邻接和路径长短进行遍历获得。
②:路径更新:上述每次点更新都会新纳入一个点进入最短路径,此步骤就是基于上述新纳入的点,去更新。