堆堆真的只能使用O(1)辅助存储吗?

时间:2014-05-15 09:52:02

标签: data-structures language-agnostic heap binary-search-tree space-complexity

使用堆优先级队列(与红黑树相对)的最大优势之一似乎是空间效率:与平衡BST不同,堆只需要O(1)辅助存储。
即,仅元素的排序足以满足堆的不变量和保证,并且不需要子/父指针。

但是,我的问题是:上面的真的是真的吗?

在我看来,为了在满足O(log n)运行时保证的同时使用基于数组的堆,数组必须是动态可扩展的

我们可以在O(1)时间内动态扩展数组的 方式是过度分配支持数组的内存,以便我们可以分摊记忆操作进入未来。

但是,那个过度分配是否意味着堆需要辅助存储?

如果上述情况属实,那似乎意味着堆叠比平衡的BST没有复杂性优势,那么,从理论的角度来看,是什么使得“有趣”呢?

1 个答案:

答案 0 :(得分:2)

您似乎混淆了二进制堆,一般堆,以及使用数组而不是显式树结构的二进制堆的实现。

二进制堆只是一个二叉树,其属性使其在理论上超出内存使用范围。它们可以在线性时间内构建,而构建BST必须花费n log n时间。例如,这可用于在优于n n log n时间内选择序列的k个最小/最大值。

将二进制堆实现为数组会产生隐式数据结构。这是理论家正式确定的主题,但大多数人并未积极追求。但无论如何,分类是合理的:要动态扩展这个结构,确实需要过度分配,但不是每个数据结构都必须动态增长,因此静态大小的预分配数据结构的情况也很有趣。

此外,快速增长所需的空间与所需空间之间存在差异,因为每个元素都比它必须大。第一种可以通过不增长来避免,并且还减少到总尺寸的任意小的常数因子,代价是运行时间的更大的常数因子。后一种空间开销通常是不可避免的,并且不能减少很多(树中的指针至少是log n位,周期)。

最后,除了二进制堆之外还有很多(斐波纳契,二进制,左派,配对......),除了二进制堆之外几乎所有堆都提供了更好的界限至少一些操作。最常见的是 reduce-key (以某种方式改变结构中已存在的键的值)和 merge (将两个堆组​​合成一个)。这些操作的复杂性对于使用优先级队列分析几种算法非常重要,因此也是进行大量研究的动机。

在实践中内存使用 很重要。但是(过度分配和没有分配),差异只是整体的一个常数因素,因此理论家对二元堆并不十分感兴趣。他们宁愿为减少键和合并获得更好的复杂性;如果数据结构占用O(n)空间,他们中的大多数都很高兴。极高的内存密度,易于实现和缓存友好性对于从业者而言更为有趣,而且他们是那些广泛赞美二进制堆的人。