从数组创建二项式堆



创建二项式堆时,我知道一般的过程是首先创建一个指向nil的头,然后慢慢插入1节点堆,并根据4种情况将相同程度的堆联合起来。

然而,我想问的是,给定一个大小为n的数组,是否有可能因为最多有floor(lg n(+1个二叉树,我们根据树的数量来划分数组,2^0,2^1,2^2等等,在每个二叉树中冒泡,使每个树都满足minheap属性?

因此例如:给定阵列[4,10,8,20,5,1,3]

  1. 如果逐个插入,根列表为3、1和4。1有5个孩子;4有孩子8,10和8有孩子20
  2. 在另一种情况下:我们有根列表4、8和1。8有10个孩子;1有孩子3,20,3有孩子5

如果这样做,会破坏二项式堆的全部目的吗?

这里似乎有三个单独的问题。

  1. 您能使用您所描述的方法从数组构建二项式堆吗
  2. 你从过程中得到不同的二项式堆,与你一次一个地把元素添加到空的二项项式堆中会得到什么相比,这是一个问题吗
  3. 这件事值得做吗

让我们逐一复习。

这种方法有效吗

是的!这是构建二项式堆的一种非常有效的方法。二项式堆的规则只要求(1(没有两个大小相同的树,(2(每个树都是堆有序的。因此,从这个意义上说,任何将元素集合转换为不同大小的堆有序二项式树集合的过程都会起作用。

我们没有得到同样的堆是不是很糟糕

不,这根本不是问题。如果你这样做,你会得到不同的二项式堆,这是正确的。但是,您也可以通过以不同的顺序添加数组中的元素来获得不同的堆。例如,如果您使用普通插入算法,并按排序顺序添加原始数组中的元素,则您得到的堆将与从左到右得到的堆具有不同的形状。(这个堆的形状与从右到左的形状不同。(通过类比二进制堆进行推理——你可以有很多不同的二进制堆,它们都有相同的元素,只是顺序不同。

这值得吗

与二进制堆相比,二项式堆有两个优点:

  1. 在最坏的情况下,将一个由n个值组成的序列插入一个空的二项式堆中需要时间O(n(;将n个元素一次一个地插入到空的二进制堆中可能需要时间Θ(n-logn(
  2. 它们支持有效的熔化。您可以在时间O(logn(内融合两个二项式堆,而使用需要时间O(n(的二进制堆

在您所描述的情况下,所有元素都是预先给定的,优势(1(并不相关,因为您也可以使用heapify算法在时间O(n(内从这些元素构建二进制堆。

类似地,如果您选择使用隐式数组表示来表示二项式堆,您将失去进行快速融合的能力,因为快速融合操作需要使用指针和链接单元格来表示树,这样在链接对象时就不需要在内存中移动对象。

所以总的来说,我想说这是一个非常酷的见解,你考虑这个很好,但从效率的角度来看,这本身可能不值得。

也就是说,有些数据结构确实使用了由使用相同原理的多棵树组成的隐式堆。平滑排序算法使用Leonardo堆,该堆使用与二项式堆相似但不相同的结构,后来的工作引入了具有另一种类似结构的白杨堆。弱堆使用了一种隐式表示,与您在这里提出的内容相差不远。

最新更新