回顾
- Floyed算法可以求任意两点之间的最短路径,但是Dijkstra算法只能求一个结点到另一个结点的最短路径,它是一个单源的最短路径算法
- Floyed算法的时间复杂度为O(n^3),故一般情况下数据范围要求在100以内
Dijkstra算法描述
- 设起点为s,
dis[v]表示从s到v的最短路径长度, 如dis[3] = 6表示从起点到3号结点的最短路径为6 pre[v]为v的前驱节点,用来输出路径- 初始化:
dis[v] = ∞(v ≠ s);//初始时路径为无穷
dis[s] = 0;//s -> s的路径为0
pre[s] = 0;
- 伪代码:
for (i = 1; i <= n ; i++)
{
//1.在没有被访问过的点中找一个顶点u使得dis[u]是最小的
//2.把u标记为已确定最短路径
//3.For循环遍历:与u相连的每个未确定最短路径的顶点v
//如果结点u的加入使得s->v的距离dis[v]变小,则更新
if (dis[u] + w[u][v] < dis[v])
{
dis[v] = dis[u] + w[u][v];
pre[v] = u;
}
}
可以通过下图来理解为什么要更新dis[v] = dis[u] + w[u][v]:

- 算法结束:
dis[v]为s到v的最短距离;pre[v]为v的前驱节点,用来输出路径。
算法的总体思想:
首先设置一个空集合,并且将所有的结点分成两类,一类是确定了最短路径的结点,另一类是未确定最短路径的结点。每次向集合中加入一个可以确定最短路的结点,然后判断会不会因为该点的加入使得某个结点到其他结点的距离变得更短,如果是,则更新最短距离。
这么多伪代码,是不是很抽象有点晕了?下面来看一个例子
Dijkstra算法举例
例:根据下图a,找出从节点1出发到各个节点的最短路径长度。

-
算法开始时,作为起点的
dis[1] = 0//结点1到其自身的距离为0
结点1到其他结点的距离为无穷,即dis[i] = 0x3f3f3f3f


-
第一轮循环发现
dis[1] = 0最小,将结点1标记成已经确定最短路径的结点(1号结点的加入会影响1号结点到2、3和4号结点的距离)。另外还需要根据图a对所有的绿点做出修改,使得dis[2] = 2,dis[3] = 4,dis[4] = 7。


-
第二轮循环发现1号结点除外,
dis[2] = 2最小,将结点2标记成已经确定最短路径的结点(2号结点的加入只会影响1号结点到3和5号结点的距离)。另外还需要根据图a对其余绿色结点做出修改,使得dis[3] = 3,dis[5] = 4。

本文详细介绍了Dijkstra算法的原理和实现过程,包括其与Floyd算法的区别,以及在处理最短路径问题时的局限性,特别是对负权边的处理。通过实例展示了Dijkstra算法如何找到从一个起点到所有其他点的最短路径,并提供了AC代码模板。此外,还讨论了算法的时间复杂度和适用场景。
17万+

被折叠的 条评论
为什么被折叠?



