Python heapq 模块

17 Mar 2025 | 6 分钟阅读

堆和优先队列简介

优先队列是相当小众但却非常有益的数据结构。这些数据结构为查找数据集中最佳元素等问题提供了非常易于使用且高效的解决方案。Pythonheapq 模块是其标准库的一部分。该模块实现了所有低级堆操作和一些常用的高级堆利用。

优先队列等数据结构在解决编写电子邮件调度程序、合并日志文件或查找地图上的最短路径等问题时,发挥着强大的工具作用。我们知道,编程充满了优化问题,目标是找到最佳元素,而优先队列以及 Python heapq 模块中的函数通常可以作为解决方案。

在接下来的教程中,我们将了解什么是堆和优先队列,以及它们之间有什么关联。我们还将探讨可以使用堆解决哪些类型的问题,以及如何使用 Python heapq 模块来解决这些问题。

让我们开始理解堆。

理解堆

堆是具体数据结构,而优先队列是抽象数据结构。具体数据结构表达实现,而抽象数据结构则规定接口。

我们通常使用堆来实现优先队列。它们是实现优先队列等抽象数据结构最著名的数据结构。

具体数据结构也表示性能保证。性能保证确保结构大小与操作所花费时间之间的关系。这些性能保证使我们能够预测程序随输入大小变化所需的时间。

理解 Python 中的 heapq 模块

我们知道,“”数据结构通常用于表示优先队列。我们可以使用 Python 标准库中的 heapq 模块来实现这一点。Python 中数据结构的特性是每次弹出最小的堆元素(最小堆)。每当弹出或推入数据元素时,都会维护堆结构。heap[0] 元素每次也提供最小的数据元素。

让我们来理解一些堆上的操作

序号。操作或函数描述
1heapify(iterable)heapify() 函数用于将可迭代对象转换为数据结构。
2heappush(heap, element)heappush() 函数用于将参数中指定的数据元素插入。可以调整顺序以维护堆结构。
3heappop(heap)heappop() 函数用于从中移除并返回最小的数据元素。也可以调整顺序以维护堆结构。
4heappushpop(heap, element)heappushpop() 函数用于在一个语句中合并 push 和 pop 操作的功能,从而提高效率。操作完成后,堆顺序将保持不变。
5heapreplace(heap, element)heapreplace() 函数用于在一个语句中插入和弹出数据元素;但是,它与上面提到的函数不同。在此函数中,首先弹出数据元素,然后插入数据元素。因此,可以返回比插入元素值更大的元素值。heapreplace() 函数用于真正返回堆中的最小值,而不是 heappushpop() 函数。
6nlargest(x, iterable, key = fun)nlargest() 函数用于返回可迭代对象中最大的 x 个元素,这些元素还满足(如果包含)。
7nsmallest(x, iterable, key = fun)nsmallest() 函数用于返回可迭代对象中最小的 x 个元素,这些元素还满足(如果包含)。

现在,让我们在接下来的部分中了解这些 heapq 模块函数的工作原理。

创建堆

我们可以使用 heapify() 函数通过数据元素列表创建堆。让我们以一个例子来理解 heapify() 函数的工作原理,该例子提供了一个数据元素列表,函数重新排列这些数据元素。它将最小的元素带到第一个位置。

示例

输出

[1, 8, 4, 23, 14, 9, 18, 43, 25, 34]

说明

在上面的示例中,我们导入了 heapq 模块并定义了一个数据元素列表。然后,我们使用 heapify() 函数重新排列数据元素,将最小的数据元素带到第一个位置。最后,我们向用户打印了列表。结果,列表中的数据元素被重新排列,最小的元素被移到了第一个位置。

现在,让我们尝试将数据元素插入堆中。

将数据元素插入堆

我们可以使用 heappush() 函数将数据元素插入堆。插入列表的元素始终添加到最后一个索引。但是,我们可以再次使用 heapify() 函数来将新插入的数据元素移到第一个索引,前提是它的值最小。让我们来看一个演示 heappush() 函数工作原理的示例。

示例

输出

[1, 8, 4, 23, 14, 9, 18, 43, 25, 34]
[1, 8, 4, 23, 14, 9, 18, 43, 25, 34, 20]

说明

在上面的示例中,我们再次导入了 heapq 模块并定义了一个列表。然后,我们将列表转换为堆并打印给用户。然后,我们使用 heappush() 函数将一个新元素添加到列表中,并向用户打印最终列表。结果,新数据元素被插入到列表的最后一个索引。

现在,让我们尝试从堆中移除元素。

从堆中移除数据元素

我们可以使用 heappop() 函数移除第一个索引的数据元素。让我们看以下示例,了解如何进行数据元素移除过程。

示例

输出

[1, 8, 4, 23, 14, 9, 18, 43, 25, 34]
[4, 8, 9, 23, 14, 34, 18, 43, 25]

说明

在上面的示例中,我们再次导入了 heapq 模块,定义了一个列表,并将其转换为堆。然后,我们使用 heappop() 函数从列表中移除第一个索引的元素。结果,元素成功移除。

现在,让我们了解如何在堆中替换元素。

替换堆中的数据元素

为了替换数据元素,我们可以使用 heapreplace() 函数。此函数始终移除堆中存在的最小数据元素,并将新传入的元素添加到某个未定义顺序的位置。

让我们以一个例子来理解在堆中替换元素的概念。

示例

输出

[1, 8, 4, 23, 14, 9, 18, 43, 25, 34]
[4, 8, 9, 23, 14, 99, 18, 43, 25, 34]

说明

在上面的示例中,我们再次导入了 heapq 模块,定义了一个列表,并创建了堆。然后,我们使用 heapreplace() 函数将列表中的一个数据元素替换为我们在参数中定义的元素。结果,最小的元素被成功替换。