实际上,Python没有独立的堆类型,而只有一个包含一些堆操作函数的模块。这个模块名为heapq(其中的q表示队列),默认为小顶堆。Python中没有大顶堆的实现。

常用的函数

函 数 描 述
heappush(heap, x) 将x压入堆中
heappop(heap) 从堆中弹出最小的元素(栈顶元素)
heapify([1,2,3]) 让列表具备堆特征
heapreplace(heap, x) 弹出最小的元素(栈顶元素),并将x压入堆中
nlargest(n, iter) 返回iter中n个最大的元素
nsmallest(n, iter) 返回iter中n个最小的元素

heappop弹出最小的元素(总是位于索引0处\栈顶),并确保剩余元素中最小的那个位于索引0处(保持堆特征)。

heapreplace等于先heappop再heappush,但是比分别调用二者快。

堆操作的时间复杂度,下面是堆的实现方法:二叉堆、斐波那契堆、严格斐波那契堆……,常见模块里用的是斐波那契堆》

代码示例:

  1. from heapq import *
  2. class KthLargest:
  3. def __init__(self, k: int, nums: List[int]):
  4. self.k = k
  5. self.q = []
  6. for x in nums:
  7. self.add(x)
  8. def add(self, val: int) -> int:
  9. if len(self.q) < self.k: # 堆没满,加入堆
  10. heappush(self.q, val)
  11. elif val > self.q[0]: # val大于堆顶元素(第K大),踢掉堆顶元素,加入val
  12. heapreplace(self.q, val)
  13. return self.q[0] # 堆顶
  1. import heapq
  2. a = [2,4,1,5,6,3]
  3. heapq.heapify(a)
  4. print(a) # [1, 4, 2, 5, 6, 3]
  1. import heapq
  2. a = [2,4,1,5,6,3]
  3. heapq.heapify(a)
  4. b = heapq.heappop(a)
  5. print(a) # [2, 4, 3, 5, 6]
  6. print(b) # 1

用小顶堆实现大顶堆

heapq在实现的时候,没有给出一个类似Java的Compartor函数接口或比较函数,开发者给出了原因见这里:http://code.activestate.com/lists/python-list/162387/

于是,人们想出了一些很NB的思路,见:http://stackoverflow.com/questions/14189540/python-topn-max-heap-use-heapq-or-self-implement

我来概括一种最简单的:

将push(e)改为push(-e)、pop(e)改为-pop(e)。

也就是说,在存入堆、从堆中取出的时候,都用相反数,而其他逻辑与TopK完全相同,看代码:

  1. class BtmkHeap(object):
  2. def __init__(self, k):
  3. self.k = k
  4. self.data = []
  5. def Push(self, elem):
  6. # Reverse elem to convert to max-heap
  7. elem = -elem
  8. # Using heap algorighem
  9. if len(self.data) < self.k:
  10. heapq.heappush(self.data, elem)
  11. else:
  12. topk_small = self.data[0]
  13. if elem > topk_small:
  14. heapq.heapreplace(self.data, elem)
  15. def BtmK(self):
  16. return sorted([-x for x in self.data])

经过测试,是完全没有问题的,这思路太Trick了……

Python里的堆heapq的更多相关文章

  1. 为什么在Python里推荐使用多进程而不是多线程

    转载  http://bbs.51cto.com/thread-1349105-1.html 最近在看Python的多线程,经常我们会听到老手说:"Python下多线程是鸡肋,推荐使用多进程 ...

  2. 为什么在Python里推荐使用多进程而不是多线程?

    最近在看Python的多线程,经常我们会听到老手说:“Python下多线程是鸡肋,推荐使用多进程!”,但是为什么这么说呢?   要知其然,更要知其所以然.所以有了下面的深入研究: 首先强调背景: 1. ...

  3. Python里format()方法基本使用

    '''第一种:自然连接''' #format 连接字符串 str = '{}使用的python是{}版本'.format('我','3.6.5') print(str) #打印结果:我使用的pytho ...

  4. Python里的单下划线,双下划线,以及前后都带下划线的意义

    Python里的单下划线,双下划线,以及前后都带下划线的意义: 单下划线如:_name 意思是:不能通过from modules import * 导入,如需导入需要:from modules imp ...

  5. 为什么在Python里推荐使用多进程而不是多线程?(为什么python多线程无法增加CPU使用率?)

    最近在看Python的多线程,经常我们会听到老手说:“Python下多线程是鸡肋,推荐使用多进程!”,但是为什么这么说呢? 要知其然,更要知其所以然.所以有了下面的深入研究: 首先强调背景:     ...

  6. Python里的类和对象简介

    ---恢复内容开始--- Python里的类  对象=属性+方法: 对象的属性主要是指主要的特征和参量,而方法主要是指函数: 类是一个具有一定特征和方法的集合,而对象是类的一个:类和对象的关系就如同模 ...

  7. python(34):为什么在Python里推荐使用多进程而不是多线程?

    最近在看Python的多线程,经常我们会听到老手说:“Python下多线程是鸡肋,推荐使用多进程!”,但是为什么这么说呢?                  要知其然,更要知其所以然.所以有了下面的深 ...

  8. <转载> 为什么在Python里推荐使用多进程而不是多线程?

    经常我们会听到老手说:“Python下多线程是鸡肋,推荐使用多进程!”,但是为什么这么说呢?                要知其然,更要知其所以然.所以有了下面的深入研究: 首先强调背景:     ...

  9. python里字典的用法介绍

    一.什么是字典 字典是python里的一种数据类型,特点是元素的无序性,和键key的唯一性.字典的创建方法是{key:values},字典里的键key只能是不可变的数据类型(整型,字符串或者是元组), ...

随机推荐

  1. Python - 基本数据类型及其常用的方法之字典和布尔值

    字典 特点:{"key1": value1, "key2":value2}  , 键值对中的值可以为任何数据类型,键不能为列表.字典(无法哈希),布尔值可以为键 ...

  2. jps的用法及常见问题介绍

    1.jps的作用 jps类似linux的ps命令,不同的是ps是用来显示进程,而jps只显示java进程,准确的说是当前用户已启动的部分java进程信息,信息包括进程号和简短的进程command. 2 ...

  3. iOS CALayer之CAEmitterLayer粒子发射器的神奇效果

    https://www.jianshu.com/p/c54ffd7412e7 想必以前QQ空间的点赞效果大家都知道吧,点赞之后按钮周围会有一圈爆裂的小圆点:还有微信的红包雨表情动画等,以及烟花,火焰效 ...

  4. numpy.flatnonzero():

    numpy.flatnonzero(): 该函数输入一个矩阵,返回扁平化后矩阵中非零元素的位置(index) 这是官方文档给出的用法,非常正规,输入一个矩阵,返回了其中非零元素的位置. 1 >& ...

  5. 支付宝单笔转账demo (改配置直接用)

    支付宝接口说明文档  https://docs.open.alipay.com/api_28/alipay.fund.trans.toaccount.transfer 需要注意的是:rsa的  公钥和 ...

  6. springcloud的服务提供者与服务消费者

    1.说明 springcloud中由服务消费者调用服务提供者一共有两种方法rest和feign 2.feign (1)使用feign的方式进行服务调,搭建服务提供者. 创建一个web项目(服务提供者) ...

  7. Sql 竖表转横表

    ) set @sql='select t3.BID,t5.UnitName,Sort,UnitTypeSort' select @sql=@sql+' , max(case t4.id when '' ...

  8. linux bash算术运算

    +, -, *(乘), /(除), **(乘方), %(取模) let var=算术运算符表达式 var=$[算术运算符表达式] var=$((算术运算符表达式)) var=$(expr $ARG1 ...

  9. android 读取.properties文件

    因为最终是通过流文件来进行properties文件读取的,所以很自然,我们想到要将文件放入到assets文件夹或者raw文件夹中了. 例如,我们这里有一个文件——>test.properties ...

  10. angular4 Form表单相关

    ng4中,有两种方式去声明一个表单 一:Template-Driven Forms - 模板驱动式表单   [引入FormsModule] 1.ngForm赋值 [可以方便的获取表单的值] <f ...