[英]Java: Using a Fibonacci Heap for Implementing Dijkstra's Algorithm
新來的,但作為客人已經潛伏了很長一段時間:)
好的,所以我一直在嘗試使用斐波那契堆(在 Java 中)執行 Dijkstra 的最短路徑算法。 經過一番搜索,我偶然發現了兩個代表斐波那契堆的現成實現。 第一個實現做得相當漂亮,可以在這里找到。 第二種實現,看似不那么優雅,是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 類(我相信它基於二進制堆本身)。 我希望修改上面的代碼,以便它使用上述斐波那契堆實現中的任何一個,而不是 Java 的 PriorityQueue。
我已經嘗試了很多,但我就是不知道如何去做,盡管我確信它就像替換幾行代碼一樣簡單。
我希望我足夠清楚。 這實際上是我在這些板上的第一篇文章。
任何幫助將不勝感激。
編輯:為了回應評論,我想我會用我的嘗試場景之一來擴展我的帖子。
這是上述 Dijkstra 方法的修改版本,使用之前鏈接的第二個斐波那契堆實現:
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 實現。 我更願意使用第一個實現(它看起來更徹底/更專業),但不幸的是我無法弄清楚如何去做。
您似乎缺少使用 Double.POSITIVE_INFINITY 添加堆中的所有節點(距離為 0.0 的源節點除外)。 這就是為什么您有 NullPointerExceptions 的原因,它們根本不在堆中。
我對幾個開源的斐波那契堆實現做了一些測試。 您可以在此處找到測試本身: Experimenting-with-dijkstras-algorithm 。 這也是我的 Dijsktra 算法的優先隊列版本: PriorityQueueDijkstra.java
JDK 不提供斐波那契堆的實現。 您必須創建自己的實現,或者您可以在這篇文章中找到一個: Fibonacci Heap
之后你所要做的就是更換
PriorityQueue<Vertex> vertexQueue = new PriorityQueue<>();
經過
FibonacciHeap<Vertex> vertexQueue = new FibonacciHeap<>();
然后只需更改對poll
的調用, add
和remove
方法,並在您提供的實現中使用它們的等效方法。
我自己使用了這個算法。 在reduceKey函數上方有一條注釋,解釋了該行為。
將指定元素的鍵降低到新的優先級。 如果新優先級大於舊優先級,則此函數將引發 IllegalArgumentException。 新的優先級必須是有限雙精度值,因此您不能將優先級設置為 NaN 或 +/- 無窮大。 這樣做也會引發 IllegalArgumentException。 假定該條目屬於該堆。 出於效率原因,這不會在運行時檢查。
至於實現,我想你會想要使用myHeap.dequeueMin().getValue()而不是myHeap.min() 。 不同之處在於, dequeueMin() 的工作方式與poll()類似,並在找到它后將其從堆中刪除。
而不是myHeap.decreaseKey(v, v.minDistance) ,只需添加它,如myHeap.insert(v, v.minDistance) 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.