【问题标题】:Building a Python implementation of min heap构建最小堆的 Python 实现
【发布时间】:2015-04-20 18:39:57
【问题描述】:

下面构建最小堆的代码有什么问题? bubble_up 方法不起作用,它得到一个超出范围的索引错误。

 def __init__(self):
    self.heap = []
    self.heap_size = 0

 def bubble_up(self, i):
    print(self.heap)
    while i // 2 > 0:
        if self.heap[i] < self.heap[i // 2]:
            tmp = self.heap[i // 2 - 1]
            self.heap[i] = self.heap[i // 2]
            self.heap[i // 2] = tmp
        print(self.heap)
        i = i // 2


def insert(self, data):
    self.heap.append(data)
    self.heap_size = self.heap_size + 1
    self.bubble_up(self.heap_size)

if __name__ == "__main__":
    min_heap = MinHeap()
    min_heap.insert(5)
    min_heap.insert(4)
    min_heap.insert(3)
    min_heap.insert(2)
    min_heap.insert(6)

【问题讨论】:

  • 你的调试说发生了什么?
  • 请问heap that comes with python有什么问题吗?
  • 索引错误,我正在尝试构建自己的 python 没有任何问题...
  • 您的调试并没有告诉您有索引错误,您的程序会告诉您。调试是确定程序为什么正在做它正在做的事情(或至少在它运行时发生了什么)的行为。编写程序然后要求 SO 为您调试不会发生。编写程序、调试它并就调试输出/信息寻求帮助都有可能发生。
  • 我没有看到的索引方法有问题。在查看我已经完成的索引方法之后,我看不到我可以做哪些进一步的调试,但用户仍然无法忍受错误或其发生的原因

标签: python algorithm python-3.x data-structures heap


【解决方案1】:
def insert(self, data):
    self.heap.append(data)
    self.heap_size = self.heap_size + 1
    self.bubble_up(self.heap_size)

您追加数据,增加heap_size,然后使用新的(增加的)堆大小调用bubble_up

在那里,你检查:

 if self.heap[i] < self.heap[i // 2]:

其中i 是堆大小。你不能这样做,如果你的堆中有3 元素,你就不能访问heap[3]。它不会存在,您唯一的有效索引是0, 1, 2

可能的修复(未经测试):使用heap_size - 1 调用bubble_up

请注意,if 中的代码看起来并不正确:

tmp = self.heap[i // 2 - 1]        # why -1 here? shouldn't this be heap[i]?
self.heap[i] = self.heap[i // 2]   # shouldn't this be the other way around? why no -1 here?
self.heap[i // 2] = tmp            # why no -1 here? shouldn't this be heap[i]?

此外,您可以将i // 2 放入此条件中,如果条件为假,则退出循环。

【讨论】:

  • 或者在增加堆大小之前做bubble_up,对于交换使用元组交换self.heap[i], self.heap[i // 2] = self.heap[i // 2], self.heap[i]。这样一来,就没有乱七八糟的临时工了
【解决方案2】:

当前发布的答案准确地描述了您收到越界错误的原因,但如果您只是用heap_size-1 调用bubble_up(),它将无法正确维护堆。请注意bubble_up() 中代码的以下部分:

while i // 2 > 0:

您当前的 while 循环语句不会将堆根的直接子代与根进行比较。假设您插入3,然后插入1。当您插入 1 时,bubble_up() 将无法正确地将插入的 1 与 3 交换,因为由于 i//2 == 0,它不会在您的 while 语句中运行交换例程,因为 i == 1 是插入位置 1进入。我会将此块切换到以下内容:

while i > 0:
    parent = i // 2
    <put your comparison & swap method here>
    i = parent

【讨论】:

    猜你喜欢
    • 2021-12-30
    • 2010-11-09
    • 2023-03-16
    • 2016-09-18
    • 2020-02-23
    • 2021-11-27
    • 2010-11-25
    • 2019-01-13
    • 1970-01-01
    相关资源
    最近更新 更多