侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

python 堆和优先队列的使用详解

Python  /  管理员 发布于 7年前   155

1.heapq

python里面的堆是通过在列表中维护堆的性质实现的。这一点与C++中heap一系列的算法类似,底层是通过堆vector的维护获取堆的性质。

关于二叉树

二叉树的特点:

二叉树是一种存储数据元素的汇集数据结构。

二叉树最重要的性质就是树的高度和树中可以容纳的最大结点个数之间的关系。树的高度类似于表长,是从根结点到其他结点的最大距离。在长为n的表里只能容纳n个结点,而在高为h的二叉树中则可以容纳大约2^h个结点,这是表和树的最大不同点。

一般的元素插入,如果是按线性顺序排列的,那么操作必然需要O(n)的时间(需要对n个数据进行移位处理),要突破这个限制,必须考虑其他数据结构的组织方式。二叉树就是一种高效插入的存储方式。

堆排序利用的是完全二叉树。

python堆的部分API,其他API查阅文档python_heap_API和  heapq的源代码

import heapq#向堆中插入元素,heapq会维护列表heap中的元素保持堆的性质heapq.heappush(heap, item)#heapq把列表x转换成堆heapq.heapify(x)#从可迭代的迭代器中返回最大的n个数,可以指定比较的keyheapq.nlargest(n, iterable[, key])#从可迭代的迭代器中返回最小的n个数,可以指定比较的keyheapq.nsmallest(n, iterable[, key])#从堆中删除元素,返回值是堆中最小或者最大的元素heapq.heappop(heap)

1.1.内置类型

从上述源代码可以看出来,heapq使用的内置的小于号,或者类的__lt__比较运算来进行比较。

def heapq_int():  heap = []  #以堆的形式插入堆  heapq.heappush(heap,10)  heapq.heappush(heap,1)  heapq.heappush(heap,10/2)  [heapq.heappush(heap,i) for i in range(10)]  [heapq.heappush(heap,10 - i) for i in range(10)]  #最大的10个元素  print heapq.nlargest(10,heap)  #输出所有元素  print [heapq.heappop(heap) for i in range(len(heap))]

1.2.元组类型

元素会默认调用内置比较函数cmp

def heapq_tuple():  heap = []  #向推中插入元组  heapq.heappush(heap,(10,'ten'))  heapq.heappush(heap,(1,'one'))  heapq.heappush(heap,(10/2,'five'))  while heap:    print heapq.heappop(heap),  print

1.2.类类型

类类型,使用的是小于号_lt_,当然没有重写但是有其他的比较函数例如:_le_,_gt_,_cmp_,也是会调用的,和小于号等价的都可以调用(测试了gt),具体的这些操作之间的关系我也没有研究过。如果类里面没有重写_lt_,会调用其他的比较操作符,从源代码可以看出来,如果没有_lt_,那么会调用_ge_函数。

所以可以重写上述的那些函数:

class Skill(object):  def __init__(self,priority,description):    self.priority = priority    self.description = description  def __lt__(self,other):#operator <     return self.priority < other.priority  def __ge__(self,other):#oprator >=    return self.priority >= other.priority  def __le__(self,other):#oprator <=    return self.priority <= other.priority  def __cmp__(self,other):    #call global(builtin) function cmp for int    return cmp(self.priority,other.priority)  def __str__(self):    return '(' + str(self.priority)+',\'' + self.description + '\')'def heapq_class():  heap = []  heapq.heappush(heap,Skill(5,'proficient'))  heapq.heappush(heap,Skill(10,'expert'))  heapq.heappush(heap,Skill(1,'novice'))  while heap:    print heapq.heappop(heap),  print 

所以如果要用到自己定义的类型,可以重写上述函数,就可以使用heapq函数了。

2.PriorityQueue

PriorityQueue的python源代码PriorityQueue 

从源代码可以看出来,PriorityQueue使用的就是heapq来实现的,所以可以认为两者算法本质上是一样的。当然PriorityQueue考虑到了线程安全的问题。

下面给出PriorityQueue的部分API和使用方法。

参考Queue

#向队列中添加元素Queue.put(item[, block[, timeout]])#从队列中获取元素Queue.get([block[, timeout]])#队列判空Queue.empty()#队列大小Queue.qsize()

2.1.内置类型

直接调用内置函数cmp进行比较

try:  import Queue as Q #python version < 3.0except ImportError:  import queue as Q #python3.*def PriorityQueue_int():  que = Q.PriorityQueue()  que.put(10)  que.put(1)  que.put(5)  while not que.empty():    print que.get(),  print

2.2.元组类型

def PriorityQueue_tuple():  que = Q.PriorityQueue()  que.put((10,'ten'))  que.put((1,'one'))  que.put((10/2,'five'))  while not que.empty():    print que.get(),  print

2.2.自定义类型

class Skill(object):  def __init__(self,priority,description):    self.priority = priority    self.description = description  #下面两个方法重写一个就可以了  def __lt__(self,other):#operator <     return self.priority < other.priority  def __cmp__(self,other):    #call global(builtin) function cmp for int    return cmp(self.priority,other.priority)  def __str__(self):    return '(' + str(self.priority)+',\'' + self.description + '\')'def PriorityQueue_class():  que = Q.PriorityQueue()  skill5 = Skill(5,'proficient')  skill6 = Skill(6,'proficient6')  que.put(skill6)  que.put(Skill(5,'proficient'))  que.put(Skill(10,'expert'))  que.put(Skill(1,'novice'))  while not que.empty():    print que.get(),  print

其他的一些方法的使用还是需要参考给出的文档的。

最后一点,让我比较奇怪的是(可能我并没有找到),没有提供像排序函数那样,指定比较方法函数,这点和c++有点区别。

这篇文档参考:参考文档

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


  • 上一条:
    Python之lambda匿名函数及map和filter的用法
    下一条:
    Python两个字典键同值相加的几种方法
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客