簡體   English   中英

Dijkstra的復雜性正確嗎?

[英]Is the complexity of Dijkstra's correct?

我對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)

我知道第3行總計為O(V),第5行總計為O(VlogV); 第7行總計為O(E),第8行隱含了reduce_key(),因此每個Relax()操作的logV。 但是在Relax()中,在d [v]> d [u] + weight並決定放松之后,我們是否應該在調用reduce_key(Q,pos,d [v]之前先查詢v在隊列Q中的位置? )用d [v]替換pos的鍵? 請注意,此查找本身的成本為O(V)。 所以每個Relax()應該花費O(V),而不是O(logV),對嗎?

有關空間復雜性的一個問題:為了比較隊列Q中的頂點,我設計了一個具有距離的struct / class頂點作為一個成員,然后我實現了operator <等以通過比較它們的距離對頂點進行排序。 但似乎我必須定義一個重復數組dist []以便在Relax()中執行dist [v] = dist [u] + weight。 如果我沒有定義重復數組,則必須查找v和u在隊列Q中的位置,然后獲取並檢查它們的距離。 應該以這種方式工作嗎? 也許我的執行不好?

除非您指定數據結構,否則 Dijkstra的算法(如您所寫)不會具有運行時復雜性。 您以某種方式正確地說“第7行”涉及O(E)運算,但讓我們看一下這些行(很幸運,Dijkstra很容易分析)。

  1. 初始化的意思是“給所有頂點一個無限的距離,除了源的距離為0。這很容易,可以在O(V)中完成。

  2. S有什么用處? 您將其“只寫”使用。

  3. 您將所有元素放入隊列。 這是龍。 什么是(優先級!)隊列? 具有操作的數據結構,可以添加,可選地減少鍵(Dijkstra需要),移除(Dijkstra中不需要),extractMin。 根據實現,這些操作具有某些運行時。 例如,您可以構建一個只是(標記)集的啞PQ-然后在固定時間內添加和減少鍵,但是要提取最小值,則必須進行搜索。 Dijkstra中的規范解決方案是使用一個隊列(如堆)來實現O(log n)中的所有相關操作。 讓我們分析這種情況,盡管從技術上講斐波那契堆會更好。 不要自己實現隊列。 使用真正的PQ實現可以節省多少錢,這真是令人驚訝。

  4. 您經歷了n次循環。

  5. 每次,您提取最小值,該最小值為O(n log n)總數(在所有迭代中)。

  6. S有什么用處?

  7. 您最多要遍歷每個頂點的邊緣一次,即,要對每個邊緣進行兩次韌化處理,因此總的來說,您可以完成循環O(E)次的所有操作。

  8. 放松意味着檢查是否必須減小鍵並這樣做。 我們已經知道,每個這樣的操作都可以在隊列(如果是堆)中添加O(log V),並且我們必須執行O(E)次,因此它是O(E log V),這占了整個運行時間。

如果您使用斐波那契堆,則可以降至O(VlogV + E),但這是學術性的。 實際的實現會調整堆。 如果您想了解實現的性能,請分析PQ操作。 但是正如我所說,如果您不完全知道自己在做什么,最好使用現有的實現。 您“在調用reduceKey之前先查找職位”的想法告訴我,在提出一個有效地使每個插入項占用O(V)(每次調用一次reduceKey進行排序)或O( V)每次提取的最小值(通過找到所需的最小值)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM