合并两个最大堆的算法?

Posted

技术标签:

【中文标题】合并两个最大堆的算法?【英文标题】:Algorithm for merging two max heaps? 【发布时间】:2010-12-08 09:30:06 【问题描述】:

有没有一种有效的算法来合并存储为数组的 2 个最大堆?

【问题讨论】:

是的。到目前为止,您尝试过什么? 高效是什么意思? 好吧,如果我只是以随机顺序将每个元素插入新堆,我认为这将是 O(nlogn) 的平均值。所以我可能正在寻找 O(log(n)^2) 把评论放在问题里面,说明你已经思考过这个问题,并且对除了琐碎的解决方案感兴趣。 @Yaron:您可以在 O(N + k) 中构建新堆。只需连接数组并使用默认方法构建一个新堆。 【参考方案1】:

这取决于堆的类型。

如果它是一个标准堆,其中每个节点最多有两个子节点,并且由于叶子最多位于两个不同的行上而被填满,那么合并的 O(n) 不会更好。

只需将两个数组放在一起并从中创建一个新堆,这需要 O(n)。

为了获得更好的合并性能,您可以使用另一个堆变体,例如可以在 O(1) 摊销中合并的 Fibonacci-Heap。

更新: 请注意,将第一个堆的所有元素一个接一个地插入第二个堆会更糟糕,反之亦然,因为插入需要 O(log(n))。 正如您的评论所述,您似乎一开始并不知道堆是如何以最佳方式构建的(同样是标准二叉堆)

    创建一个数组并以任意顺序放入两个堆的元素 现在从最低级别开始。最低级别包含大小为 1 的普通最大堆,因此此级别已完成 向上移动一个级别。当“子堆”之一的堆条件被违反时,将“子堆”的根交换为其更大的孩子。之后,2级完成 移至第 3 级。当违反堆条件时,像以前一样处理。将其与更大的孩子交换并递归处理,直到所有内容都匹配到第 3 级 ... 当您到达顶部时,您在 O(n) 中创建了一个新堆。

我在这里省略了一个证明,但您可以解释这一点,因为您已经在底层完成了大部分堆,您不必交换太多内容来重新建立堆条件。您已经在小得多的“子堆”上进行了操作,这比将每个元素插入其中一个堆时要好得多 => 然后,您每次都将在整个堆上进行操作,每次都需要 O(n) .

更新 2:二项式堆允许在 O(log(n)) 中进行合并,并且符合您的 O(log(n)^2) 要求。

【讨论】:

【参考方案2】:

大小为 n 和 k 的两个二进制堆可以在 O(log n * log k) 比较中合并。见

Jörg-R. Sack and Thomas Strothotte, An algorithm for merging heaps, Acta Informatica 22 (1985), 172-186.

【讨论】:

这需要像普通的基于指针的树一样用指针来实现堆,这与通常的做法不同。 我想说同样的话@phoeagon - 我开始阅读它,它说当它将一个数组复制到另一个数组时需要 O(k) 数据操作,但在论文的最后它指出,如果使用指针而不是基于数组的堆,则可以在恒定时间内完成数据操作,从而使您返回 O(log n * log k) 操作。【参考方案3】:

我认为在这种情况下您正在寻找的是二项式堆。

二项式堆是二项式树的集合,是可合并堆家族的成员。在 2+ 个二项式堆上进行联合(合并)的最坏情况运行时间为 O(lg n)。

更多信息请参见http://en.wikipedia.org/wiki/Binomial_heap。

【讨论】:

二项式堆不存储为数组

以上是关于合并两个最大堆的算法?的主要内容,如果未能解决你的问题,请参考以下文章

堆的相关算法

浅析STL算法中的堆排序

浅析STL算法中的堆排序

STL算法中的堆排序

基于最大堆的堆排序算法

数据结构:堆排序