python中heapq堆的讲解

目录

堆结题的基本技巧:

heapq堆的常用方法:

heapq.heappush(heap, item)

heapq.heapify(list) 

heapq.heappop(heap) 

heapq.heapreplace(heap.item) 

heapq.heappushpop(list, item)

heapq.merge(…)

heapq.nlargest(n,heap) 

heapq.nsmallest(n,heap) 

使用heapq编写优先级队列


 

堆是非线性的树形的数据结构,有两种堆,最大堆与最小堆。( heapq库中的堆默认是最小堆)

最大堆,树种各个父节点的值总是大于或等于任何一个子节点的值。

最小堆,树种各个父节点的值总是小于或等于任何一个子节点的值。

我们一般使用二叉堆来实现优先级队列,它的内部调整算法复杂度为logN。

堆是一个二叉树,其中最小堆每个父节点的值都小于或等于其所有子节点的值。

整个最小堆的最小元素总是位于二叉树的根节点。

python的heapq模块提供了对堆的支持。 heapq堆数据结构最重要的特征是heap[0]永远是最小的元素

 

堆结题的基本技巧:

常用方法:nlargest(),nsmallest(),heapify(),heappop() 

如果需要的个数较小,使用nlargest或者nsmallest比较好

如果需要的个数已经接近了序列长度,使用sorted()[:N]获取前N个数据比较好 

如果只需要唯一一个最大或最小值,则直接使用max()或者min()

 

heapq堆的常用方法:

 

heapq.heappush(heap, item)

heap为定义堆,item增加的元素

>>> import heapq
>>> h = []
>>> heapq.heappush(h,2)
>>> h
[2]

 

heapq.heapify(list) 

将列表转换为堆

>>> list = [1,2,3,5,1,5,8,9,6]
>>> heapq.heapify(list)
>>> list
[1, 1, 3, 5, 2, 5, 8, 9, 6]

 

heapq.heappop(heap) 

删除并返回最小值,因为堆的特征是heap[0]永远是最小的元素,所以一般都是删除第一个元素。

>>> list
[1, 1, 3, 5, 2, 5, 8, 9, 6]
>>> heapq.heappop(list)
1
>>> list
[1, 2, 3, 5, 6, 5, 8, 9]

 

heapq.heapreplace(heap.item) 

删除并返回最小元素值,添加新的元素值

>>> list = [1, 2, 3, 4, 5, 6, 5, 8, 9]
>>> heapq.heapreplace(list,99)
1
>>> list
[2, 4, 3, 8, 5, 6, 5, 99, 9]

 

heapq.heappushpop(list, item)

判断添加元素值与堆的第一个元素值对比;如果大,则删除并返回第一个元素,然后添加新元素值item.

                                                                     如果小,则返回item.  原堆不变。

>>> list = [2, 4, 3, 8, 5, 6, 5, 99, 9]
>>> heapq.heappushpop(list,6)
2
>>> list
[3, 4, 5, 8, 5, 6, 6, 99, 9]
>>> heapq.heappushpop(list,1)
1
>>> list
[3, 4, 5, 8, 5, 6, 6, 99, 9]

 

heapq.merge(…)

将多个堆合并

>>> h = [1000]
>>> for i in heapq.merge(h,list):
        print(i,end=" ")
3 4 5 8 5 6 6 99 9 1000 

 

heapq.nlargest(n,heap) 

查询堆中的最大n个元素

>>> list
[3, 5, 5, 9, 6, 6, 8, 99]
>>> heapq.nlargest(3,list)
[99, 9, 8]

 

heapq.nsmallest(n,heap) 

查询堆中的最小n个元素

>>> list
[3, 5, 5, 9, 6, 6, 8, 99]
>>> heapq.nsmallest(3,list)
[3, 5, 5]

 

 

使用heapq编写优先级队列

class PriorityQueue:
    def __init__(self):
        self.__queue = []
        self.__index = 0
        
    def push(self, item, priority):
        heapq.heappush(self.__queue, (-priority, self.__index, item))
        # 第一个参数:添加进的目标序列
        # 第二个参数:将一个元组作为整体添加进序列,目的是为了方便比较
        # 在priority相等的情况下,比较_index
        # priority为负数使得添加时按照优先级从大到小排序,因为堆排序的序列的第一个元素永远是最小的
        self.__index += 1
        
    def pop(self):
        # 返回按照-priority 和 _index 排序后的第一个元素(是一个元组)的最后一个元素(item)
        return heapq.heappop(self.__queue)[-1]



q = PriorityQueue()
q.push("bar", 2)
q.push("foo", 1)
q.push("gork", 3)
q.push("new", 1)
print(q.pop())
print(q.pop())
print(q.pop())
print(q.pop())

"""
gork  # 优先级最高
bar   # 优先级第二
foo   # 优先级与new相同,比较index,因为先加入,index比new小,所以排在前面
new
"""

        

 

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值