首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >批量加载最小-最大堆

批量加载最小-最大堆
EN

Stack Overflow用户
提问于 2012-07-25 16:59:35
回答 2查看 1.1K关注 0票数 2

最小-最大堆是一种堆,它可以在O(1)中找到最小和最大元素,并在O(log n)中删除它。它与经典堆密切相关,但它实际上交错了三个堆:一个最小堆和两个最大堆,其中偶数级别是最低级别,奇数级别是最大级别(因此有两个根)。经典的堆属性适用于孙子类而不是子类。min- max -heap的叶子级别本质上是在min和max堆之间共享的,此处插入的新元素可以移动到树的偶数或奇数级别。

虽然向上筛选和向下筛选是简单的修改,但当元素需要从堆的最小排序部分移动到最大排序部分时,就会出现棘手的部分。

对于典型的堆,我可以通过执行自下而上的堆修复来在O(n)中批量加载树,而显而易见的逐个插入需要O(n log n)时间。对于批量插入,我也可以这样做,而不是逐个插入它们,我可以将它们全部追加并批量修复堆。

对于最小-最大堆,我当然可以在O(n log n)中线性加载它,但我想知道是否也有一种方法可以在O(n)中批量加载它,或者自下而上地批量修复堆?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-07-30 00:44:16

我将用我到目前为止的发现来回答我自己,对于其他可能有同样问题的人来说:

最小-最大堆本质上是三合一的堆,具有共享的叶级别。

代码语言:javascript
运行
复制
       min1           <--- one min heap, first level
     /      \
   mi2       mi3      <--- third level
  /   \     /   \
 m5   m6   m7   m8    <--- fifth level
 /\   /\   /\   /\
a  b c  d e  f g  h   <--- leaf level (here: sixth level)
 \/   \/   \/   \/
 x1   x2   x3   x4    <--- fourth level
   \ /       \ /
   max1      max2     <--- two max heaps, second level

(重要说明:这并不准确,因为堆的扇出值是4!此外,这是逻辑顺序,而不是内存布局,它在级别上交错堆)叶级别的对象属于所有三个堆,这是元素从堆的最小部分转换到最大部分的地方。

现在可以计算最小堆和最大堆的大小,使用quickselect等部分排序对数据进行分区,并分别批量加载这三个部分。然而,quickselect已经和你想要的整个批量加载一样昂贵了(部分排序数据集)!另一种明显的批量装载和批量修复方法(!)堆将查看较小的子堆。在常规的最小堆中,您将查看由三个元素a、b、c组成的原子堆,并确保a是最小的。在这里,我们可以查看高度为4的堆,即15个元素:

代码语言:javascript
运行
复制
         min1
         /  \
    max1      max2
   /  \        /  \
 m1    m2    m3    m4
 /\    /\    /\    /\
a  b  c  d  e  f  g  h

并确保min1是最小的,max1和max2是两个最大的,m1-m4是下一个4个最大的,并以两个级别的步骤向上爬树(即仅限最小级别)

或者,我们可以查看大小为7 (3个级别)的堆,并区分min和max类型

代码语言:javascript
运行
复制
   min1           max1
   /  \           /  \
max1  max2     min1  min2
 /\    /\       /\    /\
a  b  c  d     a  b  c  d

确保对于最小级别我们有第一种类型,对于最高级别我们有第二种类型。然后我们需要通过所有级别。

但也许更好的解决方案是使用interval heaps。这本质上也是一个交错的最小和最大堆。但是,它们是对称交错的,并且具有相同的大小。它们看起来更容易实现,并且可以解释为如下所示的堆:

代码语言:javascript
运行
复制
      min1,max1
      /       \
min2,max2   min3,max3

有关大容量加载的详细信息,请参阅原始的间隔堆发布。

所以,如果你对可批量加载的最小-最大堆感兴趣,可以考虑考虑使用间隔堆!有些人说他们的性能要优于最小-最大-堆;它们是密切相关的,应该更容易实现。特别是,没有明显的理由说明为什么min-max-heap应该表现得更好,如果详细的复杂性分析表明,在所需的比较和交换中,它们的性能更差,我也不会感到惊讶(因为据我所知,min-max-heap需要更多的比较来验证堆的正确性)。

票数 2
EN

Stack Overflow用户

发布于 2012-07-25 18:37:31

我相信自下而上的树修复应该是可行的:

代码语言:javascript
运行
复制
def heapify(N)
  if (N is a min-node)
     if(*N > *left_child(N))
        swap(*N, *left_child(N))
     if(*N > right_child(N))
        swap(*N, *right_child(N))
     find the smallest X among N, grand-children(N)
  else
     if(*N < left_child(N))
        swap(*N, *left_child(N))
     if(*N < right_child(N))
        swap(*N, *right_child(N))
     find the largest X among N, grand-children(N)
  if(X != N)
     swap(*X, *N)
     heapify(X)

load heap in arbitrary order
for each N in bottom-up order of heap
   heapify(N)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11646126

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档