一、怎样从一个集合中获得最大或者最小的 N 个元素列表?

  heapq 模块有两个函数:nlargest() 和 nsmallest() 可以完美解决这个问题。

import heapq
nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
print(heapq.nlargest(3, nums)) # Prints [42, 37, 23]
print(heapq.nsmallest(3, nums)) # Prints [-4, 1, 2] #前面的参数可选多个元素

  两个函数都能接受一个关键字参数,用于更复杂的数据结构中:

portfolio = [
{'name': 'IBM', 'shares': 100, 'price': 91.1},
{'name': 'AAPL', 'shares': 50, 'price': 543.22},
{'name': 'FB', 'shares': 200, 'price': 21.09},
{'name': 'HPQ', 'shares': 35, 'price': 31.75},
{'name': 'YHOO', 'shares': 45, 'price': 16.35},
{'name': 'ACME', 'shares': 75, 'price': 115.65}
]
cheap = heapq.nsmallest(3, portfolio, key=lambda s: s['price'])
expensive = heapq.nlargest(3, portfolio, key=lambda s: s['price'])

PS:上面代码在对每个元素进行对比的时候,会以 price 的值进行比较。

二、如何查找最大或最小的 N 个元素

nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
import heapq
heapq.heapify(nums)
print(nums)
#[-4, 2, 1, 23, 7, 2, 18, 23, 42, 37, 8]

  堆数据结构最重要的特征是 heap[0] 永远是最小的元素。并且剩余的元素可以很
容易的通过调用 heapq.heappop() 方法得到,该方法会先将第一个元素弹出来,然后
用下一个最小的元素来取代被弹出元素 (这种操作时间复杂度仅仅是 O(log N),N 是
堆大小)。

如果想要查找最小的 3 个元素,你可以这样做:

heapq.heappop(nums)
#-4
heapq.heappop(nums)
#1
heapq.heappop(nums)
#2

当要查找的元素个数相对比较小的时候,函数 nlargest() 和 nsmallest() 是很
合适的。如果你仅仅想查找唯一的最小或最大 (N=1) 的元素的话,那么使用 min() 和
max() 函数会更快些。类似的,如果 N 的大小和集合大小接近的时候,通常先排序这
个集合然后再使用切片操作会更快点 ( sorted(items)[:N] 或者是 sorted(items)[-
N:] )。需要在正确场合使用函数 nlargest() 和 nsmallest() 才能发挥它们的优势 (如果
N 快接近集合大小了,那么使用排序操作会更好些)

三、实现一个优先级队列

怎样实现一个按优先级排序的队列?并且在这个队列上面每次 pop 操作总是返回
优先级最高的那个元素

下面的类利用 heapq 模块实现了一个简单的优先级队列:

import heapq
class PriorityQueue:
def __init__(self):
self._queue = []
self._index = 0
def push(self, item, priority):
heapq.heappush(self._queue, (-priority, self._index, item))
self._index += 1
def pop(self):
return heapq.heappop(self._queue)[-1]

下面是使用方法:

>>> class Item:
... def __init__(self, name):
... self.name = name
... def __repr__(self):
... return 'Item({!r})'.format(self.name)
...
>>> q = PriorityQueue()
>>> q.push(Item('foo'), 1)
>>> q.push(Item('bar'), 5)
>>> q.push(Item('spam'), 4)
>>> q.push(Item('grok'), 1)
>>> q.pop()
Item('bar')
>>> q.pop()
Item('spam')
>>> q.pop()
Item('foo')
>>> q.pop()
Item('grok')

仔细观察可以发现,第一个 pop() 操作返回优先级最高的元素。另外注意到如果
两个有着相同优先级的元素 ( foo 和 grok ),pop 操作按照它们被插入到队列的顺序返
回的。

python3-开发进阶 heapq模块(如何查找最大或最小的N个元素)的更多相关文章

  1. 使用deque模块固定队列长度,用headq模块来查找最大或最小的N个元素以及实现一个优先级排序的队列

    一. deque(双端队列) 1. 使用 deque(maxlen=N)会新建一个固定大小的队列.当新的元素加入并且这个队列已满的时候,最老的元素会自动被移除掉 >>> from c ...

  2. python3中的heapq模块使用

    heapq-堆排序算法 heapq实现了一个适合与Python的列表一起使用的最小堆排序算法. 二叉树 树中每个节点至多有两个子节点 满二叉树 树中除了叶子节点,每个节点都有两个子节点 什么是完全二叉 ...

  3. 查找最大或最小的 N 个元素

    使用内置的heapd模块 In [1]: import heapq In [2]: nums = [1,8, 2, 23, 7, -4, 18, 23, 42, 37, 2] In [3]: prin ...

  4. python3开发进阶-Django框架的自带认证功能auth模块和User对象的基本操作

    阅读目录 auth模块 User对象 认证进阶 一.auth模块 from django.contrib import auth django.contrib.auth中提供了许多方法,这里主要介绍其 ...

  5. python3开发进阶-Django框架的起飞加速一(ORM)

    阅读目录 ORM介绍 Django中的ORM ORM中的Model ORM的操作 一.ORM介绍 1.ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一 ...

  6. python3开发进阶-Web框架的前奏

    我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web框架了. 1.自定义web框架 import socket ...

  7. python3开发进阶-Django框架的Form表单系统和基本操作

    阅读目录 什么是Form组件 常用字段和插件 自定义校验的方式 补充进阶 一.什么是Form组件 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标 ...

  8. python3开发进阶-Django框架学习前的小项目(一个简单的学员管理系统)

    ''' 自己独立写一个学员管理系统 表结构: 班级表: -id -grade_name 学生表: -id -student_name -grade 关联外键班级表 老师表: -id -teacher_ ...

  9. python3开发进阶-Django框架起飞前的准备

    阅读目录 安装 创建项目 运行 文件配置的说明 三个组件 一.安装(安装最新LTS版) Django官网下载页面 根据官方的图版本,我们下载1.11版本的,最好用! 有两种下载方式一种直接cmd里: ...

随机推荐

  1. O(1)时间复杂度实现入栈、出栈、获得栈中最小元素、获得栈中最大元素(转)

    题目要求:定义栈的数据结构,添加min().max()函数(动态获取当前状态栈中的最小元素.最大元素),要求push().pop().min().max()的时间复杂度都是O(1). 思路解析:根据栈 ...

  2. java基础 流程控制和条件语句,循环语句

    顺序结构 程序的顺序结构: 如果代码里没有流程控制,程序是按照书写的格式从上而下一行一行执行的, 一条语句执行完之后继续执行下一条语句,中间没有判断和跳转,直到程序的结束. if语句 if语句使用bo ...

  3. java===java基础学习(4)---字符串操作

    java中的字符串操作和python中的大致相同,需要熟悉的就是具体操作形式. 关于具体api的使用,详见:java===字符串常用API介绍(转) package testbotoo; public ...

  4. 64_d2

    dtc-1.4.4-2.fc26.x86_64.rpm 20-Jun-2017 11:04 89890 dtdinst-20131210-7.fc26.noarch.rpm 11-Feb-2017 0 ...

  5. mac系统中实现vitualBox中访问内网端口

    第一步,增加外网网段 打开vitualbox后,按管理菜单,点击->主机网络管理器,如图1所示.点击创建,创建下个网络主机. 图1 然后,关掉虚拟机,虚拟机的设置中,找到网络选项卡,然后点击网络 ...

  6. [hadoop][会装]HBase集群安装--基于hadoop ha模式

    可以参考部署HBase系统(分布式部署) 和基于无HA模式的hadoop下部署相比,主要是修改hbase-site .xml文件,修改如下参数即可: <property> <name ...

  7. LeetCode解题报告—— Trapping Rain Water

    Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...

  8. hdu 2389(二分图hk算法模板)

    Rain on your Parade Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 655350/165535 K (Java/Ot ...

  9. Word Search——经典题(还没细看)

    Given a 2D board and a word, find if the word exists in the grid. The word can be constructed from l ...

  10. 181. Employees Earning More Than Their Managers

    The Employee table holds all employees including their managers. Every employee has an Id, and there ...