二进制堆与d-ary堆

时间:2015-03-18 15:42:58

标签: data-structures heap binary-heap

我已经读过二进制堆在删除最小操作时更快,并且d-ary堆在降低优先级操作时速度更快(虽然我不明白为什么),但是我也是我们读到,与二进制堆相比,4堆的速度更快。

那么我什么时候使用二进制堆?何时使用d-ary堆?我如何决定d-ary堆应该是什么?

2 个答案:

答案 0 :(得分:4)

我认为,这里有一些不同的因素可以使你所做的所有陈述成为现实。

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

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

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

编辑:正如@moreON指出的那样,对于d = 4,堆中的层数减少了两倍,每个后面的比较次数增加了一倍两个,由于缓存效果和较低的整体树高,实际上可以提供更好的整体性能。因此,它可能是超越二进制堆的好选择。

希望这有帮助!

答案 1 :(得分:0)

理论上,四进制堆比二进制堆快

inference

function graph

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