用途
迪杰斯特拉算法,用来寻找一个带权有向图中的某一顶点v0(源顶点)分别到其他顶点的最短路径集合。
算法所需基础材料声明
首先,带权有向图的权值例如邻接矩阵arcs[i][j]表示从 i 顶点到 j 顶点的距离。若两顶点不相连其值则为无穷大。
基本思想
用集合V代表图中所有顶点的集合,集合S代表已经找出了最短路径的顶点,那么集合S-V则为尚未找出最短路径的顶点集合。开始时,S中只有源点v0。我们先找出整个图中与源顶点v0直连的一条最短路径,将该路径的另一顶点加入S。这里有一个规则:假设B为尚未找出最短路径的顶点,则B的最短路径要么为与源点v0直连的一条路径,要么为S中的某条路径L与L到B的长度之和。理解了这一点之后,我们接下来在V-S中再去找下一条与v0直连的最短路径,并与第二种情况相比较,即可求出v0到B的最短路径。如此重复直到S包含所有顶点求解完毕。
算法所用辅助元素
我们需要一个数组D[n]来存储最短路径(n 为图的顶点数)。先设它的各元素的初值为上面说的第一种情况,即D[i]代表源点v0到 i 顶点的直连路径长度(即为arcs[v][i]),若不直连其值则为无穷大,即先默认所有顶点的最短路径都为第一种情况。同时还需要一个boolean类型的数组Finish[n]代表各顶点是否已经找到了最短路径(即是否被移入S集合)。
代码示例(便于理解,引用严蔚敏著清华大学出版的数据结构一书代码)
注:要点:P[v]是一个数组,它的各个分量中值为true的即为最短路径。最终的最短路径是一步步比较求出的,不是经过一次比较就可以得出
void ShortestPath(MGraph G,int v0,PathMatrix &P,ShortPathTable &D){
//用Dijkstra算法求有向网G的v0顶点到其余顶点v的最短路径P[v]及其带权长度D[V]。
//若P[v][w]为true,则w是从v0到v当前求得最短路径上的顶点。(注意此数组的理解,它表达从源点v0到v的路径是否包含w)
//final[v]为TRUE当且仅当v∈S,即已经求得从v0到v的最短路径。
for(v=0;v<G.vexnum;++v){
final[v]=FALSE;
D[v]=G.arcs[v0][v]; //D[v]的初态为源点与各顶点的直连路径长度,若没有直连则为无穷大
for(w=0;w<G.vexnum;++w){ //设空路径:P[v]的初态为:没有任何顶点是其他顶点的最短路径上的点
P[v][w]=FALSE;
}
if(D[v]<INFINITY){ //如果当前顶点与源点直连,那么源点和当前顶点是当前顶点到源点最短路径上的点
P[v][v0]=TRUE;
P[v][v]=TRUE;
}
}
D[v0]=0;final[v0]=TRUE; //初始化,v0源点属于S集合
//开始主循环,每次求得v0到某个v顶点的最短路径,并加v到S集合
for(i=1;i<G.vexnum;++i){ //循环其余G.vexnum-1个顶点循环1
min=INFINITY; //当前所知离v0顶点的最近距离,是个用于比较的变量
for(w=0;w<G.vexnum;++w){ //找出剩下的顶点中的一条最短路径循环2
if(!final[w]){ //w顶点在V-S中
if(D[w]<min){
v=w;
min=D[w]; //w顶点离v0顶点更近
}
}
}
final[v]=TRUE; //离v0顶点最近的v加入S集合
for(w=0;w<G.vexnum;++w){ //更新当前最短路径及距离:使用循环2得到的一条最短路径重构D[v]数组,
//当循环1进行完时,已使用每个最短路径重构数组D[v],所以得到了真正最短的最短路径
if(!final[w]&&(min+G.arcs[v][w]<D[w])){ //修改D[w]和P[w],w∈V-S
D[w]=min+G.arcs[v][w]; //替换路径长度
P[w]=P[v]; //替换路径,P[v]数组是已经求知的路径
P[w][w]=TRUE; //P[w]=P[v]+P[w]
}
}
}
}