2013-03-13 110 views
2

新,但都被潛伏作爲嘉賓在相當一段時間:)的Java:使用斐波那契堆在這裏實現Dijkstra算法

好了,所以我一直在嘗試使用斐波納契做Dijkstra的最短路徑算法堆(Java)。經過一番搜索之後,我設法絆倒了代表Fibonacci堆的兩個現成實現。第一個實現相當出色,可以找到here。第二種實現看起來不那麼優雅,是here

現在,這一切看起來不錯,很好。但是,我想爲我的Dijkstra算法的版本使用這些實現之一,但我還沒有任何運氣。 Dijkstra的在使用中實現如下:

public void dijkstra(Vertex source) { 
    { 
     source.minDistance = 0.; 
     PriorityQueue<Vertex> vertexQueue = new PriorityQueue<>(); 
     vertexQueue.add(source); 

     while (!vertexQueue.isEmpty()) { 
      Vertex u = vertexQueue.poll(); 

      // Visit each edge exiting u 
      for (Edge e : u.adjacencies) { 
       Vertex v = e.target; 
       double weight = e.weight; 
       double distanceThroughU = u.minDistance + weight; 
       if (distanceThroughU < v.minDistance) { 
        vertexQueue.remove(v); 
        v.minDistance = distanceThroughU; 
        v.previous = u; 
        vertexQueue.add(v); 
       } 
      } 
     } 
    } 
} 

清楚地看出,該實現使用基於Java的PriorityQueue的類(我相信是基於二進制堆本身)。 我希望修改上面的代碼,以便它使用前面提到的Fibonacci堆實現而不是Java的PriorityQueue。

我已經嘗試了很多,但我只是無法弄清楚如何去做,儘管我確信它就像替換幾行代碼一樣簡單。

我希望我很清楚。這實際上是我在這些電路板上的第一篇文章。

任何幫助將不勝感激。

編輯:在迴應的意見,我想我會擴大我的職務與我的企圖方案之一。

這裏是上述最短路徑法使用鏈接的第二斐波那契堆實現更早的修改版:

public static void computePathsFibonacciHeap(Node source) { 
    { 
     source.minDistance = 0.; 
     FibonacciHeap myHeap = new FibonacciHeap(); 
     myHeap.insert(source, source.minDistance); 

     while (!myHeap.isEmpty()) { 
      Node u = myHeap.min(); 

      // Visit each edge exiting u 
      for (Edge e : u.adjacencies) { 
       Node v = e.target; 
       double weight = e.weight; 
       double distanceThroughU = u.minDistance + weight; 
       if (distanceThroughU < v.minDistance) { 
        v.minDistance = distanceThroughU; 
        myHeap.decreaseKey(v, v.minDistance); 
        v.previous = u; 
       } 
      } 
     } 
    } 
} 

這是非常直接從僞代碼轉換(因此它完全有可能,我只是沒有轉化對的)。我得到的錯誤說「decreaseKey()得到了一個更大的值」。如果我試圖刪除最小值,我會得到一個NullPointerException。

我確定我做錯了什麼,我很想知道它是什麼。再次,這是使用第二個FHeap實現。我寧願使用第一個實現(它看起來更徹底/專業),但我不知道如何去做。

+0

向我們展示您嘗試過的以及您失敗的位置。我們將爲此提供幫助。 – 2013-03-13 17:29:11

+0

完成。謝謝你提醒我。 – 2013-03-13 17:46:36

回答

0

JDK不提供斐波那契堆的實現。你必須創建自己的實現,或者你可以找到一個在這個帖子:Fibonacci Heap

所有你必須在事後被替換

PriorityQueue<Vertex> vertexQueue = new PriorityQueue<>(); 

通過

FibonacciHeap<Vertex> vertexQueue = new FibonacciHeap<>(); 

然後只需更改來電到poll,addremove方法與您的提供的實現等效。

+0

謝謝!儘管我確實在OP中提供了相同的實現。我的問題在於,我無法確切知道如何進行所有這些調整,並讓算法再次運行。我已經完成了你以前的建議,但沒有運氣。我已經更新了OP來反映這一點。 – 2013-03-13 17:45:19

0

看來你缺少添加所有的節點堆Double.POSITIVE_INFINITY(除了源節點0。0距離)。這就是爲什麼你有NullPointerExceptions,他們根本不在堆中。

我對幾個開源的Fibonacci堆實現做了一些測試。你可以在這裏找到測試:Experimenting-with-dijkstras-algorithm。這也是我的Dijsktra算法的Priority Queue版本:PriorityQueueDijkstra.java

0

我自己使用這個算法。在decreaseKey函數之上有一個註釋,該函數解釋了行爲。

將指定元素的密鑰減少爲新的優先級。如果新的優先級大於舊的優先級,則此函數會拋出IllegalArgumentException。新的優先級必須是有限雙倍, ,因此您不能將優先級設置爲NaN或+/-無窮大。做 所以也會拋出一個IllegalArgumentException。 假設條目屬於這個堆。對於效率 的原因,這不會在運行時檢查。

至於實施,我想你會想用myHeap.dequeueMin()的getValue()代替myHeap.min()。不同的是,dequeueMin()的工作原理類似於poll(),並在找到它後將其從堆中移除。

代替myHeap.decreaseKey及(v,v.minDistance),只需添加它,就像myHeap.insert(V,v.minDistance)