我是在运筹学这门课里面接触到这个算法的,先是在书上大概理解了这种方法的人脑思维方式。但是我坚信,运用机器实现我们学到的每一个算法将会帮助我们更好地理解我们所处的信息化时代,下面就开始吧。
一、Dijkstra算法概述
Dijkstra算法是一个单向路径最短算法,也就是在一个图中不能存在负权边,该算法通过外散的形式逐步确定每一个节点到起始结点的最短路径。这种算法的具体解释在数据结构与算法、运筹学、图论等相关书籍中都有具体介绍,可以参阅相关书籍(Tips:找一些国内的比较老的书籍,或者是国外的书籍看)
二、程序实现思路
- 使用二维数组存储一个邻接矩阵什么是邻接矩阵?可以Google一下),使用这个邻接矩阵来存储一个单源有向图 。
- 为每一个节点准备三个属性,存储在三个数组中(这是程序实现的核心所在),这三个数组分别是flag,previous,distance,因此我也形象地把这种程序实现方法称为FPD法。
- 一开始的时候,程序有一张图,图中的每个节点带着三个属性数据,我们进行路径搜索的第一步是确定起点,这一步会对着三个属性数据进行一次更新,后面再对这三个数据进行(N-1)次更新就完成了,这里的N是结点数目
- 更新结束后,我们会得到两个很重要的数组previolus和distance,previous中保存的是每一个结点的前驱结点(也就是到这个结点的最短路径所经过的最后一个结点),通过previous,我们可以反向回溯得到最短路径,distance就是到每一个结点的最短路径了。
三、核心代码解析
void dijkstra(int start, int *previous, int *distance)
{
int i, j, k ;
int min, temp, flag[MAX];
//一张图中,每个节点都有三个状态参数:是否找到最短路径flag,前驱结点previous,每个结点到前驱结点的距离distance
//下面是初始化,一开始所有的结点都是没有得到最短路径,前驱结点是起始结点,每个结点到前驱结点的距离可以从邻接矩阵中获得
for(i = 0; i < Node; i++){
flag[i] = 0;
previous[i] = 0;
distance[i] = Matrix[start][i];
}
//对初始结点属性参数进行初始化
flag[start] = 1;
previous[i] = 0;
distance[start] = 0;
for(i = 1; i < Node; i++){
min = INF;
//找到各个结点中距离前驱结点最近的点以及相应的最短距离
for(j = 0; j < Node; j++){
if(flag[j] == 0 && distance[j] < min){
min = distance[j];
k = j;
}
}
//标记结点k已经找到最短路径
flag[k] = 1;
//修正前驱结点,更新起始点到各点的最短距离
for(j = 0; j < Node; j++){
temp = (Matrix[k][j] == INF ? INF : (min + Matrix[k][j]));
if(flag[j] == 0 && (temp < distance[j])){
distance[j] = temp;
previous[j] = k;
}
}
}
printf("%d", distance[6]);
}
1、当我们传入起始点后,算法首先会根据这个起始点来对所有结点的属性信息进行第一次更新,具体有哪些更新,代码中写得很清楚
2、下面继续进行N-1次更新,更新的思想是这样的:遍历所有结点,在还没有找到最短路径的结点中找到一个当前到路径最小的结点,并将这个结点号记住,然后利用这个结点号来对所有结点进行更新,具体的更新方式看代码最后一部分,然后继续循环,循环结束后,我们就可以得到我们需要的信息啦。