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


Posted in Python onMarch 05, 2019

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个数,可以指定比较的key
heapq.nlargest(n, iterable[, key])
#从可迭代的迭代器中返回最小的n个数,可以指定比较的key
heapq.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.0
except 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 相关文章推荐
用实例分析Python中method的参数传递过程
Apr 02 Python
在Python中使用lambda高效操作列表的教程
Apr 24 Python
python 数据的清理行为实例详解
Jul 12 Python
python 爬虫 批量获取代理ip的实例代码
May 22 Python
Python OpenCV对本地视频文件进行分帧保存的实例
Jan 08 Python
Python字典循环添加一键多值的用法实例
Jan 20 Python
numpy基础教程之np.linalg
Feb 12 Python
Python2.7实现多进程下开发多线程示例
May 31 Python
python实现126邮箱发送邮件
May 20 Python
Python创建简单的神经网络实例讲解
Jan 04 Python
python调用百度AI接口实现人流量统计
Feb 03 Python
教你怎么用Python生成九宫格照片
May 20 Python
Python两个字典键同值相加的几种方法
Mar 05 #Python
详解python算法之冒泡排序
Mar 05 #Python
Python字符串通过'+'和join函数拼接新字符串的性能测试比较
Mar 05 #Python
Python实现KNN(K-近邻)算法的示例代码
Mar 05 #Python
Python按钮的响应事件详解
Mar 04 #Python
Python中三元表达式的几种写法介绍
Mar 04 #Python
Python生成器的使用方法和示例代码
Mar 04 #Python
You might like
Symfony数据校验方法实例分析
2015/01/26 PHP
PHP将URL转换成短网址的算法分享
2016/09/13 PHP
PHP常用字符串输出方法分析(echo,print,printf及sprintf)
2021/03/09 PHP
Jquery ThickBox插件使用心得(不建议使用)
2010/09/08 Javascript
精心挑选的15个jQuery下拉菜单制作教程
2012/06/15 Javascript
jQuery获取注册信息并提示实现代码
2013/04/21 Javascript
JavaScript字符串对象fromCharCode方法入门实例(用于把Unicode值转换为字符串)
2014/10/17 Javascript
浅谈JS闭包中的循环绑定处理程序
2014/11/09 Javascript
jQuery循环动画与获取组件尺寸的方法
2015/02/02 Javascript
JQuery实现超链接鼠标提示效果的方法
2015/06/10 Javascript
JavaScript取得WEB安全颜色列表的方法
2015/07/14 Javascript
AngularJS 日期格式化详解
2015/12/23 Javascript
最全正则表达式总结:验证QQ号、手机号、Email、中文、邮编、身份证、IP地址等
2017/08/16 Javascript
利用three.js画一个3D立体的正方体示例代码
2017/11/19 Javascript
关于微信公众号开发无法支付的问题解决
2018/12/28 Javascript
Vue中全局变量的定义和使用
2019/06/05 Javascript
[56:20]LGD vs VP Supermajor 败者组决赛 BO3 第三场 6.10
2018/07/04 DOTA
[01:08:24]DOTA2-DPC中国联赛 正赛 RNG vs Phoenix BO3 第一场 2月5日
2021/03/11 DOTA
浅谈numpy数组的几种排序方式
2017/12/15 Python
Python编程求解二叉树中和为某一值的路径代码示例
2018/01/04 Python
python三引号输出方法
2019/02/27 Python
详解python配置虚拟环境
2019/04/08 Python
python程序变成软件的实操方法
2019/06/24 Python
Python Django form 组件动态从数据库取choices数据实例
2020/05/19 Python
详解Python中的GIL(全局解释器锁)详解及解决GIL的几种方案
2021/01/29 Python
用CSS3实现背景渐变的方法
2015/07/14 HTML / CSS
HTML5使用Audio标签实现歌词同步的效果
2016/03/17 HTML / CSS
利用HTML5中的Canvas绘制一张笑脸的教程
2015/05/07 HTML / CSS
墨西哥购物网站:Elektra
2020/01/21 全球购物
美国折扣香水网站:The Perfume Spot
2020/12/12 全球购物
涉外文秘个人求职的自我评价
2013/10/07 职场文书
建筑学推荐信
2013/11/03 职场文书
党的群众路线教育实践活动查摆问题自查报告
2014/10/10 职场文书
有限公司股东合作协议书
2014/10/29 职场文书
2015年世界水日活动总结
2015/02/09 职场文书
python字符串拼接.join()和拆分.split()详解
2021/11/23 Python