实际上,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,但是比分别调用二者快。

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

代码示例:

from heapq import *

class KthLargest:

    def __init__(self, k: int, nums: List[int]):
self.k = k
self.q = []
for x in nums:
self.add(x) def add(self, val: int) -> int:
if len(self.q) < self.k: # 堆没满,加入堆
heappush(self.q, val)
elif val > self.q[0]: # val大于堆顶元素(第K大),踢掉堆顶元素,加入val
heapreplace(self.q, val)
return self.q[0] # 堆顶
import heapq
a = [2,4,1,5,6,3]
heapq.heapify(a)
print(a) # [1, 4, 2, 5, 6, 3]
import heapq
a = [2,4,1,5,6,3]
heapq.heapify(a)
b = heapq.heappop(a)
print(a) # [2, 4, 3, 5, 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完全相同,看代码:

class BtmkHeap(object):
def __init__(self, k):
self.k = k
self.data = [] def Push(self, elem):
# Reverse elem to convert to max-heap
elem = -elem
# Using heap algorighem
if len(self.data) < self.k:
heapq.heappush(self.data, elem)
else:
topk_small = self.data[0]
if elem > topk_small:
heapq.heapreplace(self.data, elem) def BtmK(self):
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. C# 统一对 try...catch 的调用,方便保存错误日志

    每个优秀的开发人员,应该尽可能保证程序稳定运行,在确实不需要使用try...catch的地方尽尽量不要使用以提高程序性能. 但是我们不可能保证每段代码不会出错,由于出错引起的用户界面并不友好,而且有可 ...

  2. 原生js 判断变量是一个数组

    const arr = [] // 1. 最简单 ES5+ Array.isArray(arr) // 2. 兼容性好的方法,也很准确 Object.prototype.toString.call(a ...

  3. 使用video.js支持flv格式

    html5的video标签只支持mp4.webm.ogg三种格式,不支持flv格式,在使用video.js时,如果使用html5是会报错不支持. 修改了一下代码 js部分 videojs.option ...

  4. 嘴巴题3 「BZOJ1412」[ZJOI2009] 狼和羊的故事

    「BZOJ1412」[ZJOI2009] 狼和羊的故事 Description "狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......" Or ...

  5. 通过游戏学python 3.6 第一季 第六章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改 可复制直接使用 娱乐 可封装 函数

    #猜数字--核心代码--猜测次数--随机函数和屏蔽错误代码---优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改 #猜数字--核心代码--猜测次数--随机函数和屏蔽错误代码---优 ...

  6. TZ_06_SpringMVC的入门程序

    SpringMVC的入门程序 1. 创建WEB工程,引入开发的jar包 1. 具体的坐标如下 2. 配置核心的控制器(配置DispatcherServlet) 1. 在web.xml配置文件中核心控制 ...

  7. H5C3--线性渐变 linear-gradient,径向渐变radial-gradient,重复渐变radial-gradient

    一.线性渐变 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...

  8. MyEclipse使用总结——MyEclipse10.6 下添加jadClipse反编译插件[转]

    jad是一个使用比较广泛的Java反编译软件,jadClipse是jad在eclipse下的插件,下面像大家介绍下如何将jadclipse加入到MyEclipse10.X,9.X,8.X,6.X等各版 ...

  9. fastjson 对象和json互转

    list转json List<Openid> openids = od.getAll(session); String json = JSONObject.toJSONString(ope ...

  10. 【P1203】 【USACO1.1】坏掉的项链Broken Necklace

    P1203 [USACO1.1]坏掉的项链Broken Necklace 题目描述 你有一条由N个红色的,白色的,或蓝色的珠子组成的项链(3<=N<=350),珠子是随意安排的. 这里是 ...