heqpq模块提供了堆队列算法(也称为优先级队列算法)的实现。
堆是二叉树,其每个父节点的值都小于或等于其任何子节点。此实现使用所有k的heap [k] <= heap [2 * k + 1]和heap [k] <= heap [2 * k + 2]的数组,从零开始计数元素。为了进行比较,不存在的元素被认为是无限的。堆的有趣特性是它的最小元素始终是根堆[0]。
下面的API在两个方面与教科书堆算法不同:(a)我们使用基于零的索引。这使得节点的索引与其子节点的索引之间的关系不太明显,但由于Python使用基于零的索引,因此更适合。 (b)我们的pop方法返回的是最小的项目,而不是最大的项目(在教科书中称为“最小堆”;在文本中,“最大堆”由于其适合就地排序而更常见)。
要创建堆,请使用初始化为[]的列表,或者可以通过函数heapify()将填充的列表转换为堆。
heapq.heappush(heap,item)
将值项推入堆,保持堆不变。
heapq.heappop(heap)
弹出并从堆中返回最小的项,从而保持堆不变。如果堆为空,则会引发IndexError。要访问最小的项目而不弹出它,请使用heap [0]。
heapq.heappushpop(heap,item)
将项目推入堆中,然后弹出并从堆中返回最小的项目。组合的操作比heappush()更有效地运行,随后分别调用heappop()。
heapq.heapify(x)
将列表x在线性时间内就地转换为堆。
heapq.heapreplace(heap,item)
弹出并从堆中返回最小的项,然后推送新项。堆大小不变。如果堆为空,则会引发IndexError。
这一步操作比heapush()和heappush()效率更高,并且在使用固定大小的堆时可能更合适。弹出/推入组合始终从堆中返回一个元素,并将其替换为item。
返回的值可能大于添加的项目。如果不需要,请考虑改用heappushpop()。它的推/弹出组合返回两个值中较小的一个,而将较大的值保留在堆上。
该模块还提供了基于堆的三个通用功能。
heapq.merge(* iterables,key = None,reverse = False)
将多个排序的输入合并到一个排序的输出中(例如,合并多个日志文件中带有时间戳的条目)。返回排序后的值的迭代器。
类似于sorted(itertools.chain(* iterables)),但返回一个iterable,不会一次将数据全部拉入内存,并假定每个输入流都已排序(最小到最大)。
有两个可选参数,必须将其指定为关键字参数。
key指定一个自变量的键函数,该函数用于从每个输入元素中提取比较键。默认值为“无”(直接比较元素)。
reverse是一个布尔值。如果设置为True,则合并输入元素,就好像每个比较都被反转一样。为了实现类似于sorted(itertools.chain(* iterables),reverse = True)的行为,所有可迭代对象必须从最大到最小进行排序。
在版本3.5中进行了更改:添加了可选的key和reverse参数。
heapq.nlargest(n,iterable,key=None)
从iterable定义的数据集中返回包含n个最大元素的列表。 key(如果提供)指定一个参数的功能,该参数用于从iterable中的每个元素中提取比较键(例如,key = str.lower)。等效于:sorted(iterable,key = key,reverse = True)[:n]。
heapq.nsmallest(n,iterable,key=None)
从iterable定义的数据集中返回包含n个最小元素的列表。 key(如果提供)指定一个参数的功能,该参数用于从iterable中的每个元素中提取比较键(例如,key = str.lower)。等效于:sorted(iterable,key = key)[:n]。
对于n的较小值,后两个函数表现最佳。对于较大的值,使用sorted()函数更为有效。同样,当n == 1时,使用内置的min()和max()函数会更有效。如果需要重复使用这些功能,请考虑将可迭代对象转换为实际堆。
可以通过将所有值压入堆,然后一次弹出一个最小值来实现堆排序:
>>> def heapsort(iterable):
... h = []
... for value in iterable:
... heappush(h, value)
... return [heappop(h) for i in range(len(h))]
...
>>> heapsort([1, 3, 5, 7, 9, 2, 4, 6, 8, 0])
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
这类似于sorted(iterable),但与sorted()不同,此实现不稳定。
堆元素可以是元组。 这对于在跟踪主记录的同时分配比较值(例如任务优先级)很有用:
>>> h = []
>>> heappush(h, (5, 'write code'))
>>> heappush(h, (7, 'release product'))
>>> heappush(h, (1, 'write spec'))
>>> heappush(h, (3, 'create tests'))
>>> heappop(h)
(1, 'write spec')