狄杰特斯拉算法
该算法的思想是这样的:
在图中定一个出发顶点,这个顶点就是想要找到的距离其他顶点距离最小的点,从该顶点出发,记录该顶点到其他顶点的距离,如果有两个顶点之间不直接相连,就先记录为INF。记录完之后需要找到另一个顶点,要求这个顶点距离距出发顶点的距离是最近的,从这个顶点出发,记录这个顶点到其他顶点的距离(与出发顶点的距离就不用记录了)。由此可以得到第二轮出发顶点到其他顶点的距离,用这个距离结合第二轮出发顶点到第一轮出发顶点的距离,就能对第一轮的结果进行修正。由此不断进行修正,最后得到最短距离。
第一个核心方法:
private void update(int index) {
int len = 0;
//遍历邻接矩阵的matrix[index]行
for (int i = 0; i < matrix[index].length; i++) {
//len 的含义是:出发顶点到index顶点的距离 + 从index顶点到i顶点的距离的和
len = vv.getDis(index) + matrix[index][i];
//如果j顶点没有被访问过,并且len 小于出发顶点到j的距离,就需要更新
if (!vv.in(i) && len < vv.getDis(i)) {
vv.updatePre(i, index); //更新i的前驱结点为index
vv.updateDis(i, len); //更新出发顶点到i顶点的距离
}
}
}
这个核心方法的作用是对于每一轮传入的出发顶点,对各顶点与第一轮出发顶点的最小距离进行修正。形参传入的是该轮出发顶点的索引,for (int i = 0; i < matrix[index].length; i++)作用是从这个传入的顶点出发,对其他顶点进行遍历。重点在于if (!vv.in(i) && len < vv.getDis(i))这句的理解,len < vv.getDis(i)比较容易理解,这句表明找到了新的最小距离,就要进入判断体对之前的记录进行修改。但是需要注意的是!vv.in(i),这个语句和后面是且的关系。如果i顶点还没有做过出发顶点,才会去进入if判断体。如果i顶点之前做过出发顶点,就不再进入循环判断了,这是出于效率的考虑。具体需要参考第二个核心方法来理解。
第二个核心方法
//继续选择并返回新的访问顶点,比如这里的G完结后,就是A点作为新的访问顶点(注意不是出发顶点)
public int updateArray() {
int min = 65535, index = 0;
for (int i = 0; i < already_arr.length; i++) {
if (already_arr[i] == 0 && dis[i] < min) {
min = dis[i];
index = i;
}
}
already_arr[index] = 1;
return index;
}
这个核心方法目的是从没有做过出发顶点的顶点中,找到距离第一次出发顶点最近的顶点,返回的是该顶点对应的索引。结合第一个方法,可以看出,如果A顶点先于B顶点做了出发顶点,那当B成为出发顶点的时候,就不要再去记录B与A之间的距离了。原因在于,假设G顶点是第一次的出发顶点,A比B先成为出发顶点,就是因为G与A的距离比G与B的距离小。那么如果记录了B与A之间的距离,那么通过这个得到了G与A的距离等于G到B的距离加上B到A的距离,这是无效操作,因为之前已经找到了一个更短距离了。所以这也是方法一if判断用且而不是或的原因。
本文来自博客园,作者:imissinstagram,转载请注明原文链接:https://www.cnblogs.com/LostSecretGarden/p/14777681.html

浙公网安备 33010602011771号