Dijkstra算法复杂性分析误区

时间:2013-04-12 18:32:51

标签: algorithm complexity-theory graph-algorithm dijkstra

考虑到Cormen书中的以下算法:

DIJKSTRA(G,w,s)

1. INITIALIZE-SINGLE-SOURCE(G,s)
2. S <-- {0}
3. Q <-- V[G]
4. while (Q != {0})
5.    do u <-- extract-min(Q)
6.    s <-- s U {u}
7.    for each vertex v at Adj(u) 
8.            do RELAX(u,v,w)



RELAX (u,v,w)
if d[v] > d[u] + w(u,v)
    then d[v] <-- d[u] + w(u,v)
       pie(v) <--- u

我们的教授告诉我们,如果我们使用Binary Heap,Relax操作需要O(log | V |),因此 第7-8行的循环取O(| E | * log | V |)..(如果我们使用线性队列则松弛需要O(1))。 我一直在搜索谷歌一段时间,只是找不到一个很好的解释。 当我们使用二进制堆时,为什么放松操作需要O(log | V |)? 很想得到一些帮助。感谢。

4 个答案:

答案 0 :(得分:1)

我相信一旦放松了节点,就必须将它们放在二进制堆中的正确节点中。最糟糕的情况是,如果当前节点具有可怕的距离值并且是二进制堆中的叶节点,并且您刚刚找到了到达该节点的非常好的方法,则必须将该节点从堆的底部移向top保持min heap属性。节点可能需要移动的级别数是log(V) - &gt;为O(log(V))

答案 1 :(得分:1)

在Relax函数中,d [v]的键值被更新,我们需要再次维护最小堆,因为它可能违反了平均堆的属性,所以Relax的整个过程需要O(log v)时间。保持最小堆,并准备提取下一个最小值。

RELAX (u,v,w)
if d[v] > d[u] + w(u,v)
    then d[v] <-- d[u] + w(u,v)        //* updation.
       pie(v) <--- u

答案 2 :(得分:1)

在我看来,RELAX需要O(1)。由于每个边都只被查看一次,因此会生成O(E)。要点是,extract-min需要O(log(V))并使用V次,占O(V log(V))

总而言之,Djikstra在O(V log V + E)中运行(参见this page),与使用哪种堆结构无关(参见this post)。

除此之外,每当调用RELAX操作时运行min-heap(而不是每次4-8次迭代)都会产生巨大的时间开销。

答案 3 :(得分:1)

如果我们维持最小堆,则extract-min(Q)将花费O(1)时间。 O(log V)仅归因于更新和维持最小堆。