单源最短路径的Dijkstra 算法

来源:互联网 发布:h5与后端数据库 编辑:程序博客网 时间:2024/05/22 07:51

解决单源最短路径的常用算法为Dijkstra 算法,
Dijkstra算法的主要思路为, 首先求得长度最短的一条最短路径,再求得长度次短的一条最短路径,依次类推,直到从原点到其他所有顶点之间的最短路径都已求得为止。
思路的详细说明:
(1)使用一集合S来记录当前已获得最短路径的点集,一开始将起点V0,放入S中,即意味着V0到V0的最短路径已经得到,因为为0。使用一个一维数组 D[n]来记录 V0点到其他个点的最短距离,这个初始化的设定,对于点 V0与Vn直接相连,则距离即为这条边的权,否则为正无穷。
(2)求第一条最短路径,第一条最短路径为V0到其他点的最短路径,则选出这一条路径的点 V n 加入集合S中,这时,集合S中的点依然是全部最短距离已获得,对于这新加入的点Vn,其与V0的最短路径就为直接路径 D 0 n。
(3) 更新V0到其他点的最短距离,即数组D[n]中的值。由于S[n]数组中新加入了点K,则原点到S集合外的点 I的最短路径可能为之前S集合到点I的最短路径,或者为加入K点之后,经过K点的路径为最短。所以更新 D[i] = min{ D[i] , D[k] + A[k][i] },A为记录所有边的二维数组。更新最短距离,使当前的D数组中的值一直为最短路径,为原点经过集合S中的点到达 点I 的最短距离。
(4) 求下一条最短路径,根据3得到的最短路径,继续求下一条最短路径,将新的点加入S集合中,并执行(3)中操作,更新S集合到其他点的最短路径。
(5) 直到目标点Vt 加入了S集合中,更新的最短路径即为原点V0到目标点Vt的最短路径。

算法的实现:
(1) 数据结构的选择:使用二维数组A[n][n] 记录当前的全部有向路径,对于不相连的两点,设置为正无穷。使用S[n]数组记录当前已确定最短路径的点的集合,用数组D[n]记录当前源点到其他点的最短距离,用数组path[n]来记录路径,这个路径数组中, path[n]的值为原点到点n的最短路径中 点n前一个点,也就是说,最后得到完整的path数组后,要从目标点依次向前推才能得到完整的路径。
(2)数据的初始化:S数组为bool类型的数组,初始化都为false,;D[i]为 A[v][i] ,这里v为源点; 如果 i!= v 且 d[i] 不是正无穷,则path[i] = v ,否则path[i] = -1,这里就是如果两点直接相连,则最短距离的前一点就是原点,否则 设置为 -1。
(3)将源点v加入集合S中: s[v] = true 。
(4)使用for循环: 选出当前最小的d[k],最为此处最短路径,将点k计入集合S中,设置s[k] = true ,标记点k已经加入集合S,然后遍历D和Path数组,更新加入点K后的最短距离和最短路径的上一个节点。
可以知道目标点进入集合S中退出,也可以选择将全部点全部放入集合S中退出。获得最短路径。

接下来是使用C++代码的实现:

template <class T>int Choose(int *d ,bool * s){    int i,minpos;    T min;    min = INFTY;    minpos = -1;    for(i = 0 ; i < n;i++)        if(d[i] <= min && !s[i])            min = d[i];minpos = i;    return minpos;}template <class T>void Dijkstra(int v,T* d ,int* path){    int i,k,w;    if(v<0|| v> n-1) throw OutOfBounds;    bool *s = new bool[n];    for(i = 0 ; i < n ; i++){        s[i] = false;        d[i] = a[v][i];        if(i!=v && d[i] < INFTY) path[i] = v;        else path[i] = -1;    }    s[v] = true;    d[v] = 0;    for(i = 0 ; i < n ; i++){        k = Choose(d,s);        s[k] = true;        for(w = 0 ; w < n ; w++)            if(!s[w] && d[k] + a[k][w] < d[w]){                d[w] = d[k] + a[k][w];                path[w] = k;            }    }}
0 0