Python 堆的实现 heapq PriorityQueue

Python 堆的实现 heapq PriorityQueue1、系统实现 堆(heap),一种数据结构,它是一种优先队列。优先队列让你能够以任意顺序添加对象,并随时(可能是在两次添加对象之间)找出(并删除)最小的元素。相比于列表方法min,这样做的效率要高得多。 1.1 heapq 实际上,Python没有独立的堆类型,而只有一个包含一些堆操作函数的模块。这

1、系统实现

堆(heap),一种数据结构,它是一种优先队列。优先队列让你能够以任意顺序添加对象,并随时(可能是在两次添加对象之间)找出(并删除)最小的元素。相比于列表方法min,这样做的效率要高得多。

1.1 heapq

实际上,Python没有独立的堆类型,而只有一个包含一些堆操作函数的模块。这个模块名为heapq(其中的q表示队列),它包含6个函数,其中前4个与堆操作直接相关。必须使用列表来表示堆对象本身。

模块heapq中一些重要的函数

  • heappush(heap, x)         将x压入堆中
  • heappop(heap)              从堆中弹出最小的元素
  • heapify(heap)                让列表具备堆特征
  • heapreplace(heap, x)      弹出最小的元素,并将x压入堆中
  • nlargest(n, iter)              返回iter中n个最大的元素
  • nsmallest(n, iter)            返回iter中n个最小的元素

栗子:

 1 from heapq import *
 2 
 3 arr = [10, 20, 30, 40, 2, 8, 6, 4, 3, 3, 3, 1, 7, 5, 60]
 4 heap = []
 5 for i in range(len(arr)):
 6     heappush(heap, arr[i])
 7 print("heap=", heap)
 8 
 9 print("顺序为:", end="")
10 while heap:
11     print(heappop(heap), end=" ")
12 
13 print("\n###########################################")
14 
15 heapify(arr)
16 print(arr)
17 print("顺序为:", end="")
18 while arr:
19     print(heappop(arr), end=" ")

 

结果如下:

heap= [1, 3, 2, 4, 3, 6, 5, 40, 10, 20, 3, 30, 7, 8, 60]
顺序为:1 2 3 3 3 4 5 6 7 8 10 20 30 40 60
###########################################
[1, 2, 5, 3, 3, 7, 6, 4, 40, 3, 20, 8, 30, 10, 60]
顺序为:1 2 3 3 3 4 5 6 7 8 10 20 30 40 60

可以看到,使用heapify和heappush方法,heap的结果是不一样的,注意区分

 

注意:

  heapq的实现是小根堆。如果要实现大根堆,将入栈的元素变为相反数即可

 1 from heapq import *
 2 
 3 arr = [10, 20, 30, 40, 2, 8, 6, 4, 3, 3, 3, 1, 7, 5, 60]
 4 heap = []
 5 for i in range(len(arr)):
 6     heappush(heap, -arr[i])
 7 print("heap=", heap)
 8 
 9 print("顺序为:", end="")
10 while heap:
11     print(heappop(heap)*(-1), end=" ")

heap= [-60, -30, -40, -10, -3, -8, -20, -4, -3, -2, -3, -1, -7, -5, -6]
顺序为:60 40 30 20 10 8 7 6 5 4 3 3 3 2 1

 

1.2 priority_queue

queue.PriorityQueue这个优先级队列的实现在内部使用了heapq,时间和空间复杂度与heapq相同。

区别在于PriorityQueue是同步的,提供了锁语义来支持多个并发的生产者和消费者。在不同情况下,锁语义可能会带来帮助,也可能会导致不必要的开销。

调用方法:

from queue import PriorityQueue

最常用的成员函数

put()get()取队首元素的值并将其弹出. 当优先队列为空时,调用get()不会报错,而是会一直等待取出元素,可能和 PriorityQueue 支持并发的特性有关. 

full() 判断是否为满. empty() 判断是否为空.

 1 from queue import PriorityQueue
 2 
 3 q = PriorityQueue()
 4 
 5 q.put((2, 'code'))
 6 q.put((1, 'eat'))
 7 q.put((3, 'sleep'))
 8 
 9 while not q.empty():
10     next_item = q.get()
11     print(next_item)
12 
13 # 结果:
14 #   (1, 'eat')
15 #   (2, 'code')
16 #   (3, 'sleep')

 

同样的,python中的priority_queue如何从大到小排?

其实解法很简单,优先队列在插入元素的时候已经对元素做了排序,把最小的元素放在队尾,那么只要在插入的时候,让最大值被判断为最小就好了。

1 items = [3,1,2]
2 pq = PriorityQueue()
3 for element in items:
4         pq.put((-element,element))
5 print (pq.get()[1])

Python在对tuple类型作比较时,采用的是按照元素顺序,找到第一个可比较的元素进行比较。

源码如下:

Python 堆的实现 heapq PriorityQueue
Python 堆的实现 heapq PriorityQueue

 1 class PriorityQueue(Queue):
 2     '''Variant of Queue that retrieves open entries in priority order (lowest first).
 3 
 4     Entries are typically tuples of the form:  (priority number, data).
 5     '''
 6 
 7     def _init(self, maxsize):
 8         self.queue = []
 9 
10     def _qsize(self):
11         return len(self.queue)
12 
13     def _put(self, item):
14         heappush(self.queue, item)
15 
16     def _get(self):
17         return heappop(self.queue)
18 
19 
20 
21 
22 def heappush(heap, item):
23     """Push item onto heap, maintaining the heap invariant."""
24     heap.append(item)
25     _siftdown(heap, 0, len(heap)-1)
26 
27 
28 
29 
30 # 'heap' is a heap at all indices >= startpos, except possibly for pos.  pos
31 # is the index of a leaf with a possibly out-of-order value.  Restore the
32 # heap invariant.
33 def _siftdown(heap, startpos, pos):
34     newitem = heap[pos]
35     # Follow the path to the root, moving parents down until finding a place
36     # newitem fits.
37     while pos > startpos:
38         parentpos = (pos - 1) >> 1
39         parent = heap[parentpos]
40         if newitem < parent:
41             heap[pos] = parent
42             pos = parentpos
43             continue
44         break
45     heap[pos] = newitem

View Code

 

 

2、自己实现

待续

今天的文章Python 堆的实现 heapq PriorityQueue分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/51738.html

(0)
编程小号编程小号
上一篇 2023-09-01 08:06
下一篇 2023-09-01 08:17

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注