最近学习了迪杰斯特拉算法,总觉得看着头大,我自己尝试将算法过程一步步拆解,以便总结为模板使用。
迪杰斯特拉算法是干啥的
迪杰斯特拉算法一般用于求最短路径的题目,是一种常用的算法。
迪杰斯特拉算法核心思想是啥
这里借用一下大话数据结构的图片来讲解。
这张图我们是需要从源点(V0)到终点(V8)的最短路径。
这个思路是咋样呢?
这是第一步:首先从V0开始,我们设一个集合V,V0开始的话就将V0放入集合中。
第二步:我们看与V0有直接连接的顶点有哪些,有V1和V2,我们将没有直接连接的顶点距离看做∞,则其中最短的路径便是V0到V1的点,长度为1。此时我们将顶点V1放入集合V。
第三步是关键的一步:集合中已经有V1与V2了,也就是说这个集合此时与3个顶点有直接的连接(V2,V3,V4)。则此时我们的V0通过V1这个顶点,从而可找出下一个到集合的最短路径节点(V2)。
总结:思路即为不断将顶点并入集合,然后寻找集合与其他直接连接点的最短路径。
迪杰斯特拉算法模板拆解
还是这张图,我们来求源点到终点的最短路径。
按照我们前面的思路,我们可以得知我们需要:
- 一个代表∞的数==> INFINITY 65535
- 一个代表数组大小的常量 ==> MAXVEX 9
- 一个集合数组==>final [ MAXVEX ]
- 一个记录源点V0到其他顶点权重的数组 D [ MAXVEX ]
- 一个记录点与点直接前驱关系的数组 ==> P [ MAXVEX ](此数组用于输出路径过程)
当然,我们肯定需要邻接矩阵图。
现在我们的准备差不多齐全了,接下来就是我们的程序了。
初始化
int v;
int final[MAXVEX];
for(v=0;v<G.numVertexes;v++)//此处为遍历邻接矩阵的第一行
{
final[v]=0;
D[v]=G.arc[0][v];
P[v]=0;
}
D[0]=0;
final[0]=1;
//初始化完毕
这个初始化我们相当于做了两步,第一步我们是将final与P初始化为0,第二步我们是将D初始化为邻接矩阵的第一行(即V0与直接连接点的距离)。
开始循环求V0到V顶点的最短路径并且更改V0到其他点的直接长度
int v,min,w,k
for(v=1;v<G.numVertexes;v++)
{
min=INFINITY;
//寻找最短的直接路径
for(w=0;w<G.numVertexes;w++)
{
if(!final[w]&&D[w]<min)
{
k=w;
min=D[w];
}
}
final[k]=1;
//此为关键代码
for(w=0;w<G.numVertexes;w++)
{
if(!final[w]&&(min+G.arc[k][w]<D[w])
{
D[w]=min+G.arc[k][w];
p[w]=k;
}
}
}
关键代码便是更改V0与之后顶点的距离的代码,理解了这一步,整个迪杰斯特拉算法便没有难点了。