【问题标题】:Why will my build_heap method not stop running?为什么我的 build_heap 方法不会停止运行?
【发布时间】:2016-10-12 18:14:06
【问题描述】:

我为MinHeap 类编写了一个类,并创建了一个build_heap 方法。每当我调用build_heap 函数时,程序都会继续运行,除非我用键盘打断它。当我中断函数调用时,堆似乎已建立,但我很好奇为什么函数似乎无限运行。

MinHeap 类:

class MinHeap:
    def __init__(self):
        self.heap_list = [0]
        self.current_size = 0

    def perc_up(self, index):
        while index // 2 > 0:
            if self.heap_list[index] < self.heap_list[index // 2]:
                temp = self.heap_list[index // 2]
                self.heap_list[index // 2] = self.heap_list[index]
                self.heap_list[index] = temp
            index = index // 2

    def perc_down(self, index):
        while (index * 2) <= self.current_size:
            mc = self.min_child(index)
            if self.heap_list[index] > self.heap_list[mc]:
                temp = self.heap_list[index]
                self.heap_list[index] = self.heap_list[mc]
                self.heap_list[mc] = temp
            i = mc

    def min_child(self, index):
        if (index * 2 + 1) > self.current_size:
            return index * 2
        else:
            if self.heap_list[index * 2] < self.heap_list[index * 2 + 1]:
                return index * 2
            else:
                return index * 2 + 1

    def insert(self, value):
        self.heap_list.append(value)
        self.current_size += 1
        self.perc_up(self.current_size)

    def peek(self):
        return self.heap_list[1]

    def del_min(self):
        ret_val = self.heap_list[1]
        self.heap_list[1] = self.heap_list[self.current_size]
        self.heap_list.pop()
        self.perc_down(1)
        return ret_val

    def is_empty(self):
        if self.current_size == 0:
            return True
        else:
            return False

    def size(self):
        return self.current_size

    def build_heap(self, a_list):
        i = len(a_list) // 2
        self.current_size = len(a_list)
        self.heap_list = [0] + a_list[:]
        while (i > 0):
            self.perc_down(i)
            i = i - 1

调用 build_heap 时的输出:

>>> heap = MinHeap()
>>> lyst = [ 1, 3, 6, 19, 13, 4, 2]
>>> heap.build_heap(lyst)
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    heap.build_heap(lyst)
  File "C:/Users/frost_000/Documents/Python Files/MinHeap.py", line 62, in         build_heap
self.perc_down(i)
  File "C:/Users/frost_000/Documents/Python Files/MinHeap.py", line 16, in  perc_down
    while (index * 2) <= self.current_size:
KeyboardInterrupt
>>> heap.heap_list
>>> [0, 1, 3, 2, 19, 13, 4, 6]

【问题讨论】:

  • 不是答案,而是删除 perc_down 中的 'i = mc' 行。 i 在该范围内的其他任何地方都没有使用,所以充其量它是一条多余的行。
  • 您可能陷入 perc_down() 中。我没有看到你在减少 self.current_size 的任何地方,所以你会留在那个 while 循环中。
  • while (index * 2) &lt;= self.current_size: -> current_size 在这个循环中没有更新 -> 无限循环。
  • i = mc i 是什么?你不是说index = mc吗?
  • 问题,正如其他人所指出的,您需要在循环中的某处修改index 值。那些评论说您需要在该循环中修改current_size 的人是错误的。但是,在您的 del_min 函数中,您确实需要在删除项目后减少 current_size

标签: python heap interrupt


【解决方案1】:

问题是当build_help() 调用它时,perc_down() 永远不会返回。这是因为条件 (index * 2) &lt;= self.current_size 永远不会改变并且始终为 True,因为它不受 while 循环中的任何语句的影响。

随着显示的更改和添加,它现在似乎可以工作了:

class MinHeap:
    def __init__(self):
        self.heap_list = [0]
        self.current_size = 0

    def perc_up(self, index):
        while index // 2 > 0:
            if self.heap_list[index] < self.heap_list[index // 2]:
                temp = self.heap_list[index // 2]
                self.heap_list[index // 2] = self.heap_list[index]
                self.heap_list[index] = temp
            index = index // 2

    def perc_down(self, index):
        while (index * 2) <= self.current_size:
            mc = self.min_child(index)
            if self.heap_list[index] > self.heap_list[mc]:
                temp = self.heap_list[index]
                self.heap_list[index] = self.heap_list[mc]
                self.heap_list[mc] = temp
            index = mc  #### changed

    def min_child(self, index):
        if (index * 2 + 1) > self.current_size:
            return index * 2
        else:
            if self.heap_list[index * 2] < self.heap_list[index * 2 + 1]:
                return index * 2
            else:
                return index * 2 + 1

    def insert(self, value):
        self.heap_list.append(value)
        self.current_size += 1
        self.perc_up(self.current_size)

    def peek(self):
        return self.heap_list[1]

    def del_min(self):
        ret_val = self.heap_list[1]
        self.heap_list[1] = self.heap_list[self.current_size]
        self.heap_list.pop()
        self.current_size -= 1  #### added
        self.perc_down(1)
        return ret_val

    def is_empty(self):
        if self.current_size == 0:
            return True
        else:
            return False

    def size(self):
        return self.current_size

    def build_heap(self, a_list):
        i = len(a_list) // 2
        self.current_size = len(a_list)
        self.heap_list = [0] + a_list[:]
        while (i > 0):
            print('i: {}'.format(i))
            self.perc_down(i)
            i = i - 1

heap = MinHeap()
lyst = [ 1, 3, 6, 19, 13, 4, 2]
heap.build_heap(lyst)

【讨论】:

  • 这是错误的。感谢您的帮助!花了太长时间盯着它,可能一百次忽略了那个错字。
  • 不客气。不要忽略也添加到 del_min() 方法中的行——即使这不是无限循环的原因。
猜你喜欢
  • 1970-01-01
  • 2015-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-26
  • 2015-01-03
  • 1970-01-01
  • 2020-03-08
相关资源
最近更新 更多