【问题标题】:Does Python's heapify() not play well with list comprehension and slicing?Python 的 heapify() 不能很好地处理列表理解和切片吗?
【发布时间】:2010-11-06 00:14:51
【问题描述】:

我在一个我有点懒惰地实现的程序中发现了一个有趣的错误,我想知道我是否正确理解了它。简短的版本是Python's heapq implementation 实际上并没有对列表进行排序,它只是以以堆为中心的方式对列表进行摸索。具体来说,我期待 heapify() 生成一个有序列表,以有序的方式促进列表理解。

使用优先提示示例,如 Python 文档中所述:

from heapq import heapify, heappush, heappop
from random import shuffle

class Item(object):
    def __init__(self, name):
        self.name = name

lst = []

# iterate over a pseudo-random list of unique numbers
for i in sample(range(100), 15):
    it = Item("Some name for %i" % i)
    heappush(lst, (i, it))

print([i[0] for i in lst])

结果

>>> [2, 22, 7, 69, 32, 40, 10, 97, 89, 33, 45, 51, 94, 27, 67]

我们注意到,这不是列表的原始排序,而是显然一些以堆为中心的排序,如described here。我懒惰地期待这会被完全订购。

作为测试,通过 heapify() 运行列表不会导致任何变化(因为列表已经按堆排序):

heapify(lst)

print([i[0] for i in lst])

>>> [2, 22, 7, 69, 32, 40, 10, 97, 89, 33, 45, 51, 94, 27, 67]

而使用heappop() 函数遍历列表会导致按预期排序:

lst2 = []
while lst: lst2.append(heappop(lst))

print([i[0] for i in lst2])

>>> [2, 7, 10, 22, 27, 32, 33, 40, 45, 51, 67, 69, 89, 94, 97]

因此,heapq 似乎不会对列表进行排序(至少在人类意义上),而是 heappush()heappop() 函数能够理解堆有序的列表.

结果:对堆积列表的任何切片和列表理解操作都将产生无序结果。

这是真的吗,这总是是真的吗?

(顺便说一句:WinXP 系统上的 Python 3.0.1)

【问题讨论】:

    标签: python heap list-comprehension


    【解决方案1】:

    堆不是排序列表(它是部分排序二叉树的表示)。

    所以是的,你是对的,如果你期望一个 heapified 列表表现得像一个排序列表,你会失望的。您可以对堆做出的唯一排序假设是 heap[0] 始终是它的最小元素。

    (很难在您已经写的内容上添加太多内容 - 您的问题是一篇关于 How Things Are 的优秀文章。8-)

    【讨论】:

    • 是的,我发布它主要是为了让其他人遇到同样的问题时可以使用它,但很高兴知道我误解了这些文档并且应该更清楚地阅读它们。
    【解决方案2】:

    结果:任何切片和列表 对a的理解操作 heapified list 将产生非有序的 结果。

    这是真的吗,而且总是这样吗?

    如果您只想获得一次性排序列表,请使用:

    myList.sort()
    

    优先级队列/堆可用于实现排序,也可用于保持队列处于优先级形式。向堆中的插入是 O(lg n),获取是 O(1),删除是 O(lg n),这比一遍又一遍地使用整个列表要好得多。

    【讨论】:

      【解决方案3】:

      """我期待 heapify() 生成一个有序列表,以有序的方式促进列表理解。""":如果这个期望是基于对手册的阅读,你应该提出一个文档错误报告.

      """ 结果:对堆化列表的任何切片和列表理解操作都会产生无序结果。这是真的吗,并且总是如此吗?""":就像例如random.shuffle(),提到的活动没有被定义为产生“有序”的结果。它可能偶尔会产生“有序”的结果,但这是巧合,不值得依赖也不值得询问(恕我直言)。

      【讨论】:

        【解决方案4】:

        " 结果:对堆积列表的任何切片和列表理解操作都会产生无序的结果。这是真的吗,并且总是这样吗?"不,这并不总是正确的。虽然它大部分时间都是不订购的,但它有可能被订购。 heapify() 产生一个满足“堆不变量”的列表。在这种情况下,它是一个最小堆。事实证明,排序列表也满足堆不变量(参见heapq 第 4 段:“heap.sort() 保持堆不变量”)。所以从理论上讲,一个堆积的列表也有可能被排序。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-01-22
          • 2012-02-06
          • 1970-01-01
          • 2010-12-12
          • 1970-01-01
          • 1970-01-01
          • 2011-12-24
          • 1970-01-01
          相关资源
          最近更新 更多