queue标准库
Python自带的queue标准库可以实现队列、栈、优先队列
普通队列
import queue
q = queue.Queue()# 队列
#也可用q = queue.Queue(maxsize=5)创建有限大小的队列,用q.full()判断队满
#队满后再入队貌似会卡死,若需“顶出”另一端元素,可用双端队列
stack = queue.LifoQueue()# 栈
pq = queue.PriorityQueue()# 优先队列
================== RESTART: C:\Users\13272\Desktop\最大公约数gcd.py =================
>>> q.put(10)#10入队
>>> q.qsize()#队列大小
1
>>> q.get()#出队并返回队首元素
10
>>> q.empty()#队列是否为空
True
栈和优先队列
栈、优先队列的使用方法与队列类似,也有put()
、get()
、empty()
、qsize()
等方法
- 优先队列在入队时,优先将值小的元素放在队首
对于数字、字符串等,会自动比较大小
对于元组,优先按第一个值从小到大排,第一个值相同按第二个值从小到大排
然而如果有更复杂的情况,可以自定义一个类,然后在类中重载__lt__
“小于”成员函数,指定比较时采用的规则 - 若需要从大到小排列,可以在入队时,将[元素的负值]入队
例如,输入整数n和n个学生的信息,按照年龄从大到小输出学生信息,若年龄相同则按姓名字典序输出
class Stu:
def __init__(self,name,age):
self.name = name
self.age = age
def __lt__(self,another):
if self.age!=another.age:#若年龄不同,按照年龄从大到小输出
return self.age>another.age
return self.name<another.name#年龄相同,按照姓名从小到大输出
from queue import PriorityQueue
n = int(input())
pq = PriorityQueue()
for i in range(n):
name,age = input().split()
age = int(age)
pq.put(Stu(name,age))
while pq.empty()==False:
student = pq.get()
print(student.name,student.age)
================= RESTART: C:/Users/13272/Desktop/优先队列输出学生名单.py ================
5
Rose 20
Tom 17
Bob 20
Eric 17
Jack 15
Bob 20
Rose 20
Eric 17
Tom 17
Jack 15
heapq标准库
heapq标准库用于实现堆
ps.
PriorityQueue
底层实现就是堆heapq
(主要区别是,PriorityQueue
提供的是面对对象的接口,而heapq
只提供用于操作列表的函数,更多信息)
当需要每次取出前n个大的元素,应该使用堆(提供了专门函数nlargest(n,heap)
和nsmallest(n,heap)
),如LeetCode 1046. 最后一块石头的重量
堆(二叉堆)
- 堆本质上是完全二叉树,由于其特性(左儿子
2*i
,右儿子2*i+1
),直接使用数组来保存更加方便 - 堆近似理解为优先队列,不管元素的插入顺序,总能按照元素的优先级取出元素
- 堆的类型:
最大堆-任意父节点的值一定大于或等于子节点(左右子节点的关系没有要求)
最小堆-任意父节点的值一定小于或等于子节点… - 堆的底层实现:关键在于插入和删除时,利用[siftUp上浮和siftDown下沉]两种核心操作,始终保持最大/最小堆的性质
- 堆的最大优势在于:在查询前n个最大/最小的元素时就有很好的性能
Python中堆的实现
- 首先要明确,堆本质上就是列表
- Python提供heapq标准库,用于操作具有堆性质的【列表】
Python的heapq默认是小顶堆
创建堆、添加元素
- 可以先创建一个空堆,然后用
heappush(heap, num)
将数据一个一个地添加到堆中 - 也可以使用
heapify(list)
使一般的列表转化为堆
>>> from heapq import *
>>> h=[]
>>> heappush(h,4)
>>> heappush(h,7)
>>> heappush(h,3)
>>> heappush(h,2)
>>> heappush(h,8)
>>> h
[2, 3, 4, 7, 8]
>>> h=[4,7,3,2,8]
>>> heapify(h)
>>> h
[2, 4, 3, 7, 8]
删除元素
heappop(heap)
只能弹出堆顶(最小值),且保证剩余的堆仍然是小顶堆
>>> heappop(h)
2
>>> h
[3, 7, 4, 8]
查询堆中前n大/小的几个元素
nlargest(n,heap)
和nsmallest(n,heap)
>>> nlargest(3,h)
[8, 7, 4]
>>> nsmallest(3,h)
[3, 4, 7]
合并两个有序列表
heapq.merge(list1, list2)
用于将两个有序列表合并成一个新的有序列表,返回结果是一个迭代器,这个方法可以用于归并排序
>>> l1=[1,5,8]
>>> l2=[2,3,9]
>>> list(merge(l1,l2))
[1, 2, 3, 5, 8, 9]