之前一直默认Dijkstra算法时间复杂度为 o ( n 2 ) o(n^{2}) o(n2),没有思考过具体的时间复杂度,今天把这个弄清楚。
Dijkstra算法的思路与关键点
- 思路:广度优先 + 松弛
- 所有点分为两个集合 S S S和 T T T, S S S最开始只包括源点 s s s,剩余点都位于 T T T。 S S S集合表示已经计算出最短路径的点集合, T T T表示尚未计算出最短路径的点集合。
- 每次从集合 T T T中选出一个与集合 S S S距离最短的点 v v v,将点 v v v加入集合 S S S。通过点 v v v对集合 T T T中的点进行松弛,即更新 T T T中点的最短距离。
- 不断重复此步骤2,直至T集合中无法找出与集合 S S S相邻的点。
- 关键点:每次从 T T T中选出的点,距离源点的距离一定不会被松弛,因此每次选出的点都将加入集合 S S S.。
Dijkstra算法的时间复杂度
设图中的节点数为 n n n,边个数为 m m m,平均每个点的边数 k = m / n k=m/n k=m/n
算法步骤2需要执行 n − 1 n-1 n−1次,每次从集合 T T T中选出一个与集合 S S S相距最近的点,具体实现方式有4种。
- 顺序遍历集合 T T T
- 使用二叉堆作为优先队列
- 使用二项堆作为优先队列
- 使用斐波那契堆作为优先队列
前提知识:二叉堆,二项堆,斐波那契堆的各种操作时间复杂度
对于Dijkstra算法,给出时间复杂度的计算公式
( n − 1 ) ∗ ( T E X T R A C T − M I N + T D E L E T E + T D E C R E A S E − K E Y ∗ k ) (n-1)*(T_{EXTRACT-MIN}+T_{DELETE}+T_{DECREASE-KEY}*k) (n−1)∗(TEXTRACT−MIN+T