我对 Dijkstra 算法的运行时复杂性有疑问。(参见 CLRS 版本 3 中的伪代码):
DIJKSTRA(G, w, s)
1 INITIALIZE-SINGLE-SOURCE(G, s)
2 S ← ∅
3 Q ← V[G]
4 while Q != ∅
5 do u ← EXTRACT-MIN(Q)
6 S ← S ∪ {u}
7 for each vertex v ∈ Adj[u]
8 do RELAX(u, v,w)
我知道line3是O(V),line5总共是O(VlogV);line7 总共是 O(E),line8 意味着 reduction_key() 所以 logV 对于每个 Relax() 操作。但是在relax()中,在d[v]>d[u]+weight之后决定放宽,我们不应该在调用reduce_key(Q, pos, d[v]之前查找队列Q中v的位置吗? ) 用 d[v] 替换 pos 的键?请注意,此查找本身的成本为 O(V)。所以每个 Relax() 应该花费 O(V),而不是 O(logV),对吧?
关于空间复杂度的问题:为了比较队列 Q 中的顶点,我设计了一个结构/类顶点,距离作为一个成员,然后我实现了诸如 operator< 通过比较它们的距离来对顶点进行排序。但似乎我必须定义一个重复的数组 dist[] 才能在 Relax() 中执行 dist[v] = dist[u]+weight。如果我没有定义重复数组,我必须在队列 Q 中查找 v 和 u 的位置,然后获取并检查它们的距离。它应该以这种方式工作吗?或者我的实现不好?