【问题标题】:Binary heaps vs d-ary heaps二进制堆与 d-ary 堆
【发布时间】:2015-05-21 11:53:11
【问题描述】:

我读过二进制堆在删除最小操作时更快,而 d-ary 堆在降低优先级操作时更快(虽然我不明白为什么),但后来我也读到了 4 堆与二叉堆相比,它们都更快。

那么我什么时候使用二叉堆,什么时候使用二叉堆?我如何决定 d 应该是什么 d 堆?

【问题讨论】:

  • Dijkstra 算法使用的降低优先级操作比删除最小操作更多。 (假设边多于顶点。)

标签: data-structures heap binary-heap


【解决方案1】:

这里有几个不同的因素在起作用,我相信,这些因素使您所做的所有陈述都成为可能。

要了解这是为什么,让我们首先考虑一下 d-ary heap 中的 reduce-key 是如何工作的(我们不需要单独讨论二进制 heap,因为二进制 heap 只是一个 2-ary heap )。当执行递减键时,我们改变树中节点的优先级,然后反复将其与其父节点交换,直到它到达树的根或它的优先级最终变得小于其父节点的优先级。在最坏的情况下,我们必须进行交换的次数由 d-ary 堆的高度给出。由于 d-ary heap 的每一层中的节点数在每一步都以 d 的因子呈指数增长,因此 d-ary heap 的高度为 O(logd n) = O(日志 n / 日志 d)。这意味着如果增加 d 的值,则 d-ary 堆的高度会降低,因此减少键和插入将花费更少的时间。如果你考虑一个极端的情况,如果你有一个 10100-ary 堆,那么树中的层数将比二叉堆中的层数少 100 倍左右,所以减少键或insert 将快 100 倍左右。

另一方面,想想出队操作是如何工作的。为了执行出队,我们将最后一个叶子交换为根,然后重复执行以下操作:我们扫描当前节点的所有子节点,如果其中任何一个小于当前节点,我们将当前节点与最小的孩子。这些迭代中的每一个都需要 O(d) 总比较来找到最小的孩子,并且迭代次数由树中的层数给出,我们之前看到的是 O(log n / log d)。这意味着在 d-ary 堆中出队的成本是 O(d log n / log d)。由于 d 的增长速度比 log d 快得多(实际上是指数级地快),当我们增加 d 时,出队的渐近(和实际)成本开始上升。例如,在 10100-ary 堆中,您可能必须在每一步将每个节点与 10100 个子节点进行比较,这将需要很长时间!因此,随着 d 越来越大,d-ary 堆的出队速度往往比二叉堆慢得多。

现在回答您的最后一个问题:鉴于此处的信息,4 元堆怎么可能胜过二元堆?老实说,我不知道这是否属实,但它 (a) 可能取决于硬件并且 (b) 不会让我感到惊讶。请记住,前面的所有分析都试图通过查看堆中的层数和进行的交换次数等数量来限制 d-ary 堆操作的成本。但是,这忽略了许多其他因素,例如寻找父母和孩子的成本以及参考地点。对于其中的第一个,请注意,在 d-ary 堆中,您可以通过将索引除以 d 来找到父节点。对于 d 是 2 的完美幂,这可以通过简单、廉价的位移来实现(因为 n / 2k = n >> k)。对于奇数或不是 2 的幂的数字,这需要除法,这(在某些架构中)比位移更昂贵。此外,还有参考位置的影响。如今的计算机在内存中有大量的缓存层,访问缓存中的内存的成本可能比访问不在缓存中的内存的成本快数百或数千倍。当您增加 d 堆中 d 的值时,树中的层数会减少,访问的元素会更靠近,从而提供更好的局部性。找到最佳位置可能需要一些实验,如果碰巧 d = 4 是您机器上最好的,那就去吧!

编辑:正如@moreON 指出的那样,对于 d = 4,堆中的层数减少了两倍,之后的比较次数增加了二,由于缓存效果和较低的整体树高,这实际上可能会提供更好的整体性能。因此,它可能是优于二叉堆的好候选。

希望这会有所帮助!

【讨论】:

  • 对于出队操作,对于较大的 D 也有一些更好的参考局部性,因为您有更多的子节点在内存中都是连续的要考虑。正因为如此和你所说的,它可以双向进行。同样对于 2 对 4(而不是 10^100)至关重要,4-ary 的级别(大约)是 2-ary 的一半,每个节点的子节点数量是基本相同数量的两倍,但在大堆,整体上更好的参考位置,如上所述。
  • @moreON 我没有想到带有多个入队操作的大 d 的位置优势。感谢分享!
【解决方案2】:

理论上四元堆比二元堆快

inference

function graph

由于 3 元堆在 a 中的成本很大,并且 f(k=4)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-25
    • 2015-07-16
    • 1970-01-01
    • 1970-01-01
    • 2014-06-23
    • 2020-09-09
    • 2013-08-29
    • 1970-01-01
    相关资源
    最近更新 更多