簡體   English   中英

使用優先隊列的 Prims 算法的復雜性?

[英]Complexity of Prims Algorithm using Priority Queue?

我正在使用鄰接矩陣,優先級隊列是數據結構。

根據我的計算,復雜度是V^3 log V

  • While 循環: V
  • 檢查相鄰頂點: V
  • 如果條目已經存在,則檢查隊列並更新: V log v

但是,我到處都讀到復雜度是V^2

請解釋。

如果您使用斐波那契堆,則提取最小值是O(lg V)攤銷成本,更新其中的條目是O(1)攤銷成本。

如果我們使用這個偽代碼

while priorityQueue not empty
    u = priorityQueue.exractMin()
    for each v in u.adjacencies
        if priorityQueue.contains(v) and needsWeightReduction(u, v)
            priorityQueue.updateKeyWeight(u, v)

假設實現對於priorityQueue.contains(v)needsWeightReduction(u, v)都有固定的時間。

需要注意的是,您可以稍微更緊地檢查鄰接關系。 雖然外部循環運行V次,並且檢查任何單個節點的鄰接關系是最壞的V操作,但您可以使用聚合分析來意識到您永遠不會檢查超過E鄰接關系(因為只有 E 邊緣)。 E <= V^2 ,所以這是一個更好的界限。

所以,你有外循環 V 次,內循環 E 次。 提取最小值運行V次,更新堆中的條目運行E次。

  V*lgV + E*1
= O(V lgV + E)

同樣,由於E <= V^2你可以使用這個事實來替代並得到

  O(V lgV + V^2)
= O(V^2)

但在考慮稀疏圖時,這是一個更寬松的界限(盡管是正確的)。

使用基於最小堆的優先級隊列,時間復雜度為 O(ElogV)。

正如您所說,外部 while 循環是 O(V),因為它遍歷每個頂點,因為每個頂點都需要添加到 MST 一次。

對於 while 循環中考慮的每個頂點,需要執行以下兩個步驟:

  1. 選擇下一條邊添加到 MST。 根據基於最小堆的優先級隊列的屬性,根元素總是最小的元素。 因此,選擇下一個邊,即成本最低的邊,將是對根元素的 O(1) 提取。 提取后剩余的值需要以維持優先級隊列的方式移動。 由於隊列表示平衡二叉樹,因此在最壞的情況下,這種偏移可能會在 O(logV) 內發生。

  2. 更新優先級隊列。 與新頂點相關的邊可能需要在隊列中更新它們的成本,因為我們現在將考慮與新添加的頂點及其鄰居之間的邊相關的成本(但是,如果它們通過一條邊與先前添加的頂點相鄰)成本低於新引入的邊緣,成本不會更新,因為我們正在尋找最低成本)。 這也是 O(logV),因為在最壞的情況下,一個頂點需要在代表隊列的平衡二叉樹的整個長度上移動。

步驟 1 發生 V 次,因為它在 while 循環中發生一次,所以總共是 O(VlogV),步驟 2 在最壞的情況下發生 E 次,其中每條邊都連接到當前頂點,因此它們都需要更新,這意味着它是 O(ElogV) 總數。 設置是 O(E),因為它需要將優先級隊列中的每個邊成本初始化為無窮大。

使用基於最小堆的優先級隊列的總時間復雜度 = O(E + VlogV + ElogV) = O(ElogV)

當您閱讀復雜度為 O(V^2) 時,您可能正在查看不使用堆的實現。 在這種情況下,外部 while 循環仍然是 O(V)。 瓶頸在於選擇要添加到 MST 的下一個頂點的步驟,即 O(V),因為您需要檢查與每個相鄰節點相關的成本以找到最低成本,這在最壞的情況下意味着檢查所有其他節點。 因此復雜度為 O(V*V) = O(V^2)。

此外,在非常密集的圖中,O(ElogV) 變為 O(V^2),因為在任何圖中,最多可以有 E = V^2 個總邊。

如果不使用優先級隊列,則使用二叉堆它包括兩個基本步驟: 1.Insertion 使用插入排序算法的插入時間復雜度在最壞情況下為 O(E^2) 2.Deletion 刪除每個出隊需要 O(1) 並且dequeue 相當於頂點數,如果使用映射,否則將幾乎相同所以,這里的總時間復雜度是 O(V+E^2)

暫無
暫無

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

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