从数组创建二项式堆?

问题描述

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

但是,我想问一个给定的大小为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 log n)。
  2. 它们支持有效的融合。您可以在时间O(log n)中融合两个二项式堆,而对于二进制堆则需要时间O(n)。

在您描述的情况下,事先将所有元素都提供给您,优点(1)并不重要,因为您还可以在O(n)的时间内使用heapify从这些元素构建二进制堆算法。

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

因此,总的来说,我想这是一个非常酷的见解,您正在考虑这一点很棒,但是从效率的角度来看,这本身并不值得。

话虽这么说,但有些数据结构确实使用了由多个使用相同原理的树构成的隐式堆。 Smoothsort算法使用Leonardo堆,该堆使用与二项式堆相似但不相同的结构,后来的工作引入了杨树堆,后者具有另一个类似的结构。弱堆使用隐式表示形式,与您在此处提出的建议相距不远。