【问题标题】:Dijkstra on Java: Getting Interesting Results Using a Fibonacci Heap vs. PriorityQueueJava 上的 Dijkstra:使用 Fibonacci Heap 与 PriorityQueue 获得有趣的结果
【发布时间】:2023-03-08 19:30:02
【问题描述】:

我最近使用两种数据结构对 Dijkstra 算法的运行时间进行了初步比较,基于 Java 的 PriorityQueue(如果我没记错的话,基于二进制堆)和 Fibonacci 堆。我使用 Java 的 currentTimeMillis() 进行计算。我最终得到的结果非常有趣。这是我的一个测试用例的输出:

Running Dijkstra's with 8 nodes and 27 links
- Execution time with binary heap: 1 miliseconds
- Execution time with Fibonacci heap: 4 miliseconds

诚然,我目前缺乏数据集,上面的图表是我最大的(我计划尽快制作更多)。但这有意义吗?我一直认为斐波那契堆比其他数据结构更快,因为与其他数据结构相比,它们的摊销运行时间。我不确定这 3 毫秒的差异是从哪里来的。 (我在 Intel Core Ivy Bridge i7-3630M 处理器上运行它,如果有帮助的话。)

注意:我偶然发现了this thread,这可能解释了这个问题,但我仍然不清楚为什么斐波那契堆版本需要更长的时间。根据该线程,这可能是因为我的图不够密集,因此减少键操作的数量不足以使斐波那契堆的性能真正发挥作用。这是唯一合理的结论,还是我还遗漏了什么?

【问题讨论】:

  • 您需要一个比 8 个节点和 27 个链接大几个数量级的数据集才能获得有意义的基准。
  • 是的,我现在明白了。我将不得不调查它,看看我能做些什么。谢谢。

标签: java data-structures heap dijkstra fibonacci-heap


【解决方案1】:

斐波那契堆渐近比二叉堆(Java 的优先级队列中使用的数据结构)快,因为 Dijkstra 的算法在斐波那契堆中需要 O(m + n log n) 时间,但 O (m log n) 使用二叉堆。这意味着对于大而密集的图,在最坏的情况下,斐波那契堆会更快。

虽然斐波那契堆比二叉堆渐进地快,但众所周知,它们具有很大的常数因子,并且斐波那契堆上的许多基本操作需要很长时间才能完成。从长远来看,它们会胜过二叉堆,但对于小图,常数项可能太大,以至于斐波那契堆实际上更慢。

其次,比较渐近运行时间(O(m + n log n) 与 O(m log n))。如果您使用的图是稀疏的(即 m = O(n)),那么这两个渐近运行时都是相同的(O(n log n))。在这种情况下,斐波那契堆的理论优势不存在,二叉堆可能是更好的选择。

最后,请注意,在这种情况下,大 O 表示法指的是最坏情况的行为,而不是平均情况。不久前有一篇论文表明,对于某种类型的随机图,Dijkstra 的期望算法远低于最坏情况下减少键和出列操作的数量。在这种情况下,即使在大型图上,二叉堆的性能也可能优于斐波那契堆,因为最坏情况下的行为可能永远不会被触发。

希望这会有所帮助!

【讨论】:

  • 确实有帮助,非常感谢!所以我想我并没有做错什么,毕竟。看到这一点我真的很惊讶(即使它是一个微小的差异),但现在它是有道理的。此外,您会很高兴知道我使用您自己的斐波那契堆实现来进行这些测试:)
  • 你能把我们链接到那篇论文吗?或者给出它的名字?谢谢。 :)
【解决方案2】:

斐波那契堆具有更快的渐近线,但它们的常数因子不一定很好。对于超过 100 万左右的可笑输入,它们可能会更快,但对于小输入,二进制堆可能会明显更快。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    • 2023-02-05
    • 2014-03-14
    • 2021-03-10
    • 1970-01-01
    • 1970-01-01
    • 2020-08-02
    相关资源
    最近更新 更多