这里很新,但是作为嘉宾潜伏了很长一段时间:)
好的,所以我一直在尝试使用Fibonacci堆(在Java中)做Dijkstra的最短路径算法。经过一些搜索,我设法偶然发现了两个代表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。
我已经尝试了很多,但我无法弄清楚如何做到这一点,虽然我确信它就像更换几行代码一样简单。
我希望我足够清楚。这是我在这些主板上的第一篇文章。
非常感谢任何帮助。
编辑: 为了回应评论,我想我会用我的一个尝试场景扩展我的帖子。
以下是使用之前链接的第二个Fibonacci堆实现的上述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实现。我宁愿使用第一个实现(它只是看起来更彻底/专业),但遗憾的是我无法弄清楚如何。
答案 0 :(得分:0)
JDK没有提供Fibonacci堆的实现。您必须创建自己的实现,或者在此帖子中找到一个:Fibonacci Heap
之后您需要更换
PriorityQueue<Vertex> vertexQueue = new PriorityQueue<>();
通过
FibonacciHeap<Vertex> vertexQueue = new FibonacciHeap<>();
然后,只需将调用更改为poll
,add
和remove
方法及其提供的实现中的等效方法。
答案 1 :(得分:0)
似乎您缺少使用Double.POSITIVE_INFINITY添加堆的所有节点(除了距离为0.0的源节点)。这就是你有NullPointerExceptions的原因,它们根本就不在堆中。
我对几个开源的Fibonacci Heap实现进行了一些测试。您可以在此处找到测试本身:Experimenting-with-dijkstras-algorithm。这也是我的Dijsktra算法的优先级队列版本:PriorityQueueDijkstra.java
答案 2 :(得分:0)
我自己使用这个算法。 decreaseKey 函数上方有一条注释,用于解释行为。
将指定元素的键减少到新优先级。如果新优先级大于旧优先级,则此函数抛出一个 IllegalArgumentException异常。新的优先级必须是有限的双倍, 所以你不能将优先级设置为NaN或+/-无穷大。干 所以也抛出IllegalArgumentException。 假设该条目属于此堆。为了效率 原因,这不是在运行时检查。
至于实现方式,我认为您希望使用 myHeap.dequeueMin()。getValue()而不是 myHeap.min()。区别在于, dequeueMin()的工作方式与 poll()类似,并在找到它后将其从堆中删除。
而不是 myHeap.decreaseKey(v,v.minDistance),只需添加它,例如 myHeap.insert(v,v.minDistance)。