38 最短路经
目录
最短路经
1. 最短路径
广度优先算法可以计算连通图中,从一个顶点到另一顶点的最短路径,但前提是图上的每条边的权重相同。那如何计算全重不同的图的最短路径呢?最出名的莫过于 Dijkstra 算法。
1.1 Dijkstra
Dijkstra 算法是贪心算法。贪心算法的递归过程差不多是这样:假设我们计算图 G 上顶点 u 到顶点 v 的最短距离;对于到顶点 v 的所有输入边的顶点集合 S,如果我们知道 u 到 S 中每个顶点的最短距离,那我们就能计算出 u 到 v 的最短距离。整个 Dijkstra 算法计算过程比较复杂,我们结合代码来看。
2. 实现
2.1 Dijkstra
|
|
AdaptableHeapPriorityQueue 是我们在堆中实现的优先队列。之所以使用这个优先队列,是因为我们要不断的在队列中更新顶点的距离,以保证从优先队列取出的是当前距离最小的顶点。
整个代码的时间负载度分成两个部分:
- 一是 while + for 内对顶点和边的迭代,因为每个顶点和每条边最多被迭代一次,所以时间负载度是O(n+m);
- 二是对优先队列的操作,包括:
addremove_minupdate
在堆一节中AdaptableHeapPriorityQueue被实现为一个堆,上述所有操作的时间复杂度都是 logn,因此总的时间复杂度是 O((n+m)logn)。
AdaptableHeapPriorityQueue 还有其他实现方式,比如一个未排序的数组,此时 remove_min 为 O(n),其他两个操作的时间复杂度都是O(1),此时总体的时间复杂度就是 O(n*n + m)。因此使用哪种实现方式更优取决于图的稀疏程度。
需要注意的是与前面类似,对于 d,pre, pdlocator,cloud 如果顶点可以用 0 到 n-1 进行编号, 它们都可以用数组代替,或者将作为顶点属性来记录。
2.2 重建最短路径树
上面我们计算出从 src 到各个顶点的最短距离,但是并没有明确计算出获取最短剧路的路径。最短路径的重建有两种方式:
- 向上面代码中那样,使用
pre记录到达每个顶点的前一个顶点。 - 是直接从
cloud的返回值进行重建。
|
|