查找存储为Ahnentafel数组的二进制最大堆的最小元素

时间:2012-05-29 20:11:27

标签: data-structures heap

我有一个二进制最大堆(顶部的最大元素),我需要通过每次到达时删除最小元素来保持它的常量(例如20个元素) 20个要素。二进制堆存储在一个数组中,节点i的子节点为2 * i和2 * i + 1(i基于零)。在任何时候,堆都有'n_elements'元素,介于0和20之间。例如,数组[16,14,10,8,7,9,3,2,4]将是一个有效的最大二进制堆, 16岁有14岁和10岁的孩子,14岁有8岁和7岁的孩子......

为了找到最小的元素,似乎通常我必须遍历从n_elements / 2到n_elements的数组:最小元素不一定是数组中的最后一个元素。

因此,仅使用该数组,似乎任何寻找/移除最小elt的尝试都至少为O(n)。这是对的吗?

3 个答案:

答案 0 :(得分:5)

对于任何给定的有效Max Heap,最小值仅在叶节点处。接下来的问题是如何在数组中找到堆的叶节点?如果我们仔细观察数组的最后一个节点,它将是最后一个叶节点。通过公式

获取叶节点的父节点
parent node index = (leaf Node Index)/2

从索引(parent node index +1)开始线性搜索到最后一个叶节点索引获取该范围内的最小值。

FindMinInMaxHeap(Heap heap)
   startIndex = heap->Array[heap->lastIndex/2]
   if startIndex == 0
          return heap->Array[startIndex]
   Minimum = heap->Array[startIndex + 1]
   for count from startIndex+2 to heap->lastIndex
            if(heap->Array[count] < Minimum)
                Minimum := heap->Array[count]
   print Minimum

答案 1 :(得分:3)

我无法想到通过单独使用堆来查找和删除最大堆中的最小元素的O(n)性能更好。您可以采取的一种方法是:

如果您自己创建此堆数据结构,则可以保留指向数组中最小元素位置的单独指针。因此,每当将新元素添加到堆中时,请检查新元素是否更小。如果是,则更新指针等。然后找到最小的元素将是O(1)

MBo在关于如何在每次删除后获得下一个最小元素的评论中提出了一个很好的观点。你仍然需要做O(n)的事情来找到每次删除后的下一个最小元素。因此删除仍然是O(n)。但找到最小的元素是O(1)

如果你还需要更快的删除,你还需要维护所有元素的最小堆。在这种情况下,删除将是O(log(n))。插入将花费2倍的时间,因为你必须插入两个堆,它也将占用2倍的空间。

顺便说一下,如果你在任何时间点只有20个元素,那么这并不重要(除非它是一个家庭作业问题,或者你只是为了好玩而做)。只有当你计划将它扩展到数千个值时才真正重要。

答案 2 :(得分:0)

有minmax堆数据结构:http://en.wikipedia.org/wiki/Min-max_heap。当然,它的代码相当复杂,但是有两个独立的堆,我们必须使用大量的额外空间(对于第二个堆,用于维持一对一的映射)并完成两次工作。