Python的heapq模块
heapq是堆队列的意思,从名字中也可以看出来,heap_queue。
一、基本概念
1.1 什么是堆?
堆是一个完全二叉树,完全二叉树的是指除了最后一层之外,其他所有层的结点都是满的,而最后一层不满的节点是左节点。
1.2 什么是最小堆?
最小堆每个父节点的值都会小于等于所有子节点的值,索引从0开始的话,可以得到heap[k]<=heap[2k+1] and heap[k]<=heap[2k+2]
。下面是一个最小堆的示意图。有意思的是,最小堆的根节点的值一定是全局最小的。
知道了堆是怎样的一种结构,接下来我们来分析一下堆的输入和输出情况。
二、加深理解
给你一个序列
b = [18, 1, 20, 10, 5, 200]
然后让你画出它的节点图,怎么画?
第一个节点是18,直接画
第二个节点是1,比18要小,交换位置
第三个数字是20,满足条件,直接画上去
第四个数字是10,添加上去的时候会发现不满足条件,于是修改交换
第五个数字加上去,不满足条件,交换位置
第六个数字加上去,满足条件,不移动位置。
这就是我们最后得到的一个二叉树,也叫最小堆,如果要输出这个堆,按照宽度优先的输出策略,输出的结果应该为:
1, 5, 20, 18, 10, 200
也即按照一行一行从左到右输出。
接下来利用python
程序输出看看我们的推理是否正确?具体的heapq
的使用会在下面介绍。
import heapq
# 创建一个列表
b = [18, 1, 20, 10, 5, 200]
# 将列表中的数据添加到堆中
heapq.heapify(b)
print("b = ", b)
输出结果为:
b = [1, 5, 20, 10, 18, 200]
可以看到我们的推导是正确的。
三、python中的heapq的用法
3.1 创建堆
heapq有两种方式创建堆:
- 使用一个空列表,然后使用heapq.heappush()函数把值加入堆中
- 使用heap.heapify(list)转换列表成为堆结构
import heapq
# 第一种
nums = [2, 3, 5, 1, 54, 23, 132]
heap = []
for num in nums:
heapq.heappush(heap, num) # 加入堆
import heapq
# 第二种
nums = [2, 3, 5, 1, 54, 23, 132]
heapq.heapify(nums)
3.2 访问堆的内容
堆创建好后,可以通过heapq.heappop()
函数弹出堆中最小值,注意,这里每次弹出的都是全局最小值。
import heapq
nums = [2, 43, 45, 23, 12]
heapq.heapify(nums)
print(heapq.heappop(nums))
输出为:
2
四、实践运用–我们能用堆来做些什么呢?
排序
根据上面的描述,每次弹出的都是针对于当前堆的全局最小值,如果一直弹弹弹,直到堆为空,不就是进行一次从小到大排序的吗?
import heapq
# 创建一个列表
b = [18, 1, 20, 10, 5, 200]
# 将列表中的数据添加到堆中
heapq.heapify(b)
# 弹出所有值
for i in range(len(b)):
out = heapq.heappop(b)
print(out, end=" ")
输出为:
1 5 10 18 20 200
import heapq
# 创建一个列表
b = [18, 1, 20, 10, 5, 200]
# 将列表中的数据添加到堆中
heapq.heapify(b)
# 使用列表生成式来接收排序之后的值
sorted_list = [heapq.heappop(b) for i in range(len(b))]
print("排序后的列表为:", sorted_list)
输出为:
排序后的列表为: [1, 5, 10, 18, 20, 200]
参考内容: