微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

这种逻辑可能吗? 问题:二进制最小堆,优先级队列,在索引0处插入但根在索引1处

如何解决这种逻辑可能吗? 问题:二进制最小堆,优先级队列,在索引0处插入但根在索引1处

我有一个二进制最小堆优先级队列的工作代码(具有所需的效率),该队列使索引0为空,并且根节点位于索引1(子级为2i和2i + 1)。我将新值插入到堆末尾第一个可用的空白处的堆中,然后应用heapify-up(如果需要)将其移至其各自的位置。这是教科书规定的技术。

但是,在我的作业中,教授希望我们将新值插入索引0,然后应用heapify-down将其移至其相应位置,但根索引仍应位于索引1 。

当从索引1(extractMin)中删除一个项目时,也将使用heapify-down方法代码,并且必须四处移动项目以维护优先级队列和二进制最小堆结构。在这种情况下,索引0处没有任何项目...所有值都在索引> = 1处。

在这些情况下,是否可以为使用heapify-down方法保持O(log n)的效率?我应该创建2个heapify down方法吗?目前,我的方法大约有30行代码,并且为了修复该代码以满足分配要求,我的代码越来越多,几乎包含了100行以上的代码,其中包含大量的if / else语句。

感谢您的帮助!

更新:与教授交谈,他告诉我,他只是希望我们使用堆中的所有索引,因此不会浪费空间。我应该不理会他先前关于在索引0 + heapify-down插入的电子邮件和分配的详细信息,而只需将索引0用作swap方法。目前,我正在使用一个temp变量,所以交换过程分3个步骤完成,但是我正在按照他的说明修改它,以利用arr [0]处的空间-现在是4个步骤,但它满足了他的要求:-)

解决方法

如您所言,extractMin()可以以传统方式实现,我将重点介绍如何实现自上而下的add(elt)方法。

保证O(log n)性能的一个关键方面是使堆数组紧凑,以便具有n元素且索引为1的根的堆始终将这些元素存储在位置1到{ {1}}(含)。通常,这是通过在索引n处添加一个新元素,然后对其进行渗滤直到恢复heap属性来实现的。为了自上而下执行此操作,我们要考虑沿相同的路径,但从上到下而不是从下到上。无论哪种方式,顶点集都是相同的,并且可以通过将目标顶点索引n + 1依次减半来确定。使用您选择的名称作为使用Python的默认权限,以下简单函数生成给定参数n的索引集:

n

例如,运行def index_path(n): bits = n.bit_length() return [n >> (bits - i) for i in range(1,bits)] 会产生index_path(42),您可以很容易地确认这与使用自下而上方法评估的是同一组索引。只要我们坚持通过堆的这条路,就可以保持紧凑性。

然后是算法

  • 将新元素放置在数组的索引0
  • 更新[1,2,5,10,21],即堆中的元素数量
  • 生成从顶部(1)一直到但不包括最后一个索引(n)的索引集
  • 遍历索引集
    • 如果当前迭代值等于或小于0 th 值,则前进到下一个;
    • 否则,将0 th 值替换为当前迭代器的值
  • 在索引n上附加或插入(视情况而定)第0 th

Python的快速实现:

n

这是一个测试运行:

class MyHeap:
    def __init__(self):
        self.ary = [None]
        self.size = 0

    def add(self,elt):
        self.ary[0] = elt
        self.size += 1
        for index in index_path(self.size):
            if self.ary[0] < self.ary[index]:
                self.ary[0],self.ary[index] = self.ary[index],self.ary[0]
        if len(self.ary) > self.size:
            self.ary[self.size] = self.ary[0]
        else:
            self.ary.append(self.ary[0])
        self.inspect()

    def inspect(self):
        print(self.ary,self.size)

产生:

test_data = [42,42,96,17,1,3,29,12,39]
test_heap = MyHeap()
test_heap.inspect()
for x in test_data:   
    test_heap.add(x)

可以很容易地在每个阶段将其确认为有效堆。

与自下而上的方法不同,此版本不能短路。每次都必须经过整个路径。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。