Data structures 分裂二项式堆

Data structures 分裂二项式堆,data-structures,Data Structures,我正试图想出一个新的想法,通过给定一个 问题是如何将二项式堆(大小n)拆分为二项式堆 大小为k(k

我正试图想出一个新的想法,通过给定一个

问题是如何将二项式堆(大小n)拆分为二项式堆
大小为k(k您可以使用中值算法在
O(n)
时间中找到集合的
kth
最大元素

当您拥有该值时,您可以从原始堆中读取所有值(不需要提取,它们的顺序在读取时并不重要,只在写入新数组时才重要。这还有一个额外的好处,即不会弄乱原始堆.Yay。),并根据它们与
kth
值的关系将其放入大堆或小堆中。每次提取都是
O(1)
并发生
n次。每个插入都是
O(lg n)
并出现
n次

Total running time: n +  n  + n lg n = O(n lg n)
                    |    |       |
             selection   |    inserts
                     extraction

在k*log(n)中,只需从原始堆中删除k个元素并将它们移动到新的不同堆中即可。(假设堆是一个最小堆,如果它是一个最大堆,那么它可以在(n-k)log(n)中以相同的方式进行)

因为二项式堆的树可以表示为n的二进制数字,您可以通过在n和k之间进行二进制长减法(每次需要“借用”时)将堆拆分为O(log(n))一个数字,你把它分成半棵树。它与二项式树合并完全相同,但在树上使用二进制长减法而不是加法。

使用此拆分操作的好处是什么(堆被拆分为50/50是有原因的)?到目前为止,您尝试了什么?如果您已经在执行O(nlogn)操作,为什么不直接对原始堆中的所有值进行排序,找到第k个数字,将大于该数字的所有数字插入一个堆,将小于该数字的所有数字插入另一个堆?似乎比使用中值算法更简单…@Gal,因为不需要这样做。您的函数以最少的工作量获得了30%的速度提升(算法已经为我们编写,开发时间很短)。此外,您甚至不需要从原始数组中提取。你可以把它们全部读出来然后插入。这是另一个30%的速度增加。我刚刚意识到了这一点,但是您已经可以在O(n)中重建整个堆,所以没有理由将其拆分为O(nlogn)。此外,您还可以在O(logn)时间和O(1)时间内拆分二项式堆space@TᴏᴍᴇʀWᴏʟʙᴇʀɢ只有在移除单个元素时才能在
O(n)
(实际上,它是
O(h)
)中重建堆。至于空间限制,如果您想要一个单独的数据结构,它将需要它自己的数组。@corsiKa Ok,但您仍然可以在O(logn)时间内完成。就像合并2个二项堆可以在O(logn)中完成,在二项堆的树上使用二进制长加法,每次有提示时合并2棵树,拆分二项堆可以同样完成,但使用二进制长减法,每次需要借用一个数字时拆分一棵树。对不起,英语不好