Python3通过heapq模块创建堆

Python3中内置的堆模块为:heapq

使用时直接导入即可:

import heapq

可以打印出heapq内置的方法:

print(dir(heapq))

在具体介绍几个常用函数之前,要明确一下,heapq默认支持的堆类型为:小根堆

如果,希望使用大根堆,可通过对元素反向比较大小实现。

所谓反向比较大小,对int来说,即原本使用heapq存x为小根堆,那么现在使用heapq存(-x)即为大根堆了。

对于非int这种类型的数据,可通过重写大小比较函数:__lt__,__ge__等。

具体方法此处不赘述,本文主要记录heap的函数使用方法。

一、堆的内置函数

1. heapq.heapify(l: list)

将列表l转换为heap,在原地转换,线性时间复杂度。

2. heapq.heappush(heap: list, item)

将item添加进heap中,并重新维护heap成为一个堆。

FAQ:如何创建一个heap?

两种方式,1. 对于一个已经有数据的list,使用heapify函数直接将其转换为一个heap;2. 对于一个没有数据的空list,不断的使用heappush,构建一个heap。

3. heapq.heappop(heap: list)

弹出heap中的最小值作为返回值,并重新维护heap成为一个堆。当heap为空时,调用此函数会引发IndexError

注意:在Python的heap模块中没有提供类似top()这样的函数,无法通过函数获取怼的根,可直接使用heap[0]进行索引。

4. heapq.heappushpop(heap: list, item)

将item添加进heap中,弹出heap中的最小值(即根)作为返回值,并重新维护heap成为一个堆。即,该函数相当于先调用了heappush(),再调用了heappop()(注意,确是有此顺序关系,即如果新插入的item为最小值会被弹出)。根据官方文档,该函数会比先后调用heappush,heappop效率要高。

import random
import heapq

l = [2,3,4,5,6]
random.shuffle(l)

heapq.heapify(l)
print(heapq.heappushpop(l, 1))  # 1
print(heapq.heappushpop(l, 7))  # 2
print(l)    # [3, 4, 6, 7, 5]

5. heapq.heapreplace(heap: list, item)

heappushpop相似,但顺序相反,先弹出heap的最小值(即根)作为返回值,再将item添加进heap中,并重新维护heap成为一个堆。同样,该操作比先后调用heappop,heappush效率要高。

二、基于堆的算法

1. heapq.merge(*iterators, key=None, reverse=False)

将多个已排序的输入合成为一个已排序的输出(迭代器对象)。注意该函数不会检查输入的数据是否已排序,而是假定每个输入流都是从小到大排序正确的。

key:指定带有单个参数的函数对象,用于从每个输入元素中提取比较键,默认为None,即直接比较元素值。

reverse:是否逆序,默认由小到大。注意,当标记reverse=True时,输入数据应该也保持逆序,即假定输入是由大到小排序正确的

l1 = [2,4,6,7]
l2 = [1,3,5,8]
# [1, 2, 3, 4, 5, 6, 7, 8]
print(list(heapq.merge(l1, l2)))
# 以下为错误用法示例
# [2, 4, 6, 7, 1, 3, 5, 8]
print(list(heapq.merge(l1, l2, reverse=True)))

l1 = [7,6,4,2]
l2 = [8,5,3,1]
# 以下为错误用法示例
# [7, 6, 4, 2, 8, 5, 3, 1]
print(list(heapq.merge(l1, l2)))
# [8, 7, 6, 5, 4, 3, 2, 1]
print(list(heapq.merge(l1, l2, reverse=True)))

2. heapq.nlargest(n: int, iterable, key=None)

从可迭代的iterable对象数据中返回前n个最元素组成的列表

key:指定带有单个参数的函数对象,用于从每个输入元素中提取比较键,默认为None,即直接比较元素值。

3. heapq.nsmallest(n: int, iterable, key=None)

从可迭代的iterable对象数据中返回前n个最元素组成的列表

key:指定带有单个参数的函数对象,用于从每个输入元素中提取比较键,默认为None,即直接比较元素值。

注意:函数2函数3n值较小时性能较好。对于较大的值,建议使用sorted()函数进行排序,当n为1时,建议使用min(),max()函数替代。如果需要对同一数据对象重复调用这两个函数,建议将数据对象转换为真正的堆。

三、堆排序

基于heap的内置函数,构建一个堆,并以此弹出,即可完成堆排序。

def heapsort(iterable):
    l = []
    for v in iterable:
        heapq.heappush(l, v)

    return [heapq.heappop(l) for i in range(len(l))]

# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(heapsort([1, 3, 5, 7, 9, 2, 4, 6, 8, 0]))

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值