Python的heapq模块学习和使用

Python的heapq模块

heapq是堆队列的意思,从名字中也可以看出来,heap_queue。

一、基本概念

1.1 什么是堆?

堆是一个完全二叉树,完全二叉树的是指除了最后一层之外,其他所有层的结点都是满的,而最后一层不满的节点是左节点。

1.2 什么是最小堆?

最小堆每个父节点的值都会小于等于所有子节点的值,索引从0开始的话,可以得到heap[k]<=heap[2k+1] and heap[k]<=heap[2k+2]。下面是一个最小堆的示意图。有意思的是,最小堆的根节点的值一定是全局最小的。

img

知道了堆是怎样的一种结构,接下来我们来分析一下堆的输入和输出情况。

二、加深理解

给你一个序列

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]

参考内容:

详解数据结构—堆

Python标准库模块之heapq

heapq — 堆队列算法 官方文档

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值