《Redis应用实例》书摘(21):优先队列¶
优先队列是一种常见的数据结构,这种队列中的每个元素都有一个优先级,而优先级则决定了元素在队列中的出队顺序。
在Redis中实现优先队列最直接的方法就是使用有序集合——通过将优先队列元素映射为有序集合成员,并将元素的优先级映射为有序集合成员的分值,程序就可以通过操纵有序集合来操纵优先队列。
代码清单 CODE_PRIORITY_QUEUE 展示了基于有序集合实现的优先队列程序。
代码清单 CODE_PRIORITY_QUEUE 优先队列 priority_queue.py
def none_or_single_queue_item(result):
"""
以{item: priority}形式返回result列表中包含的单个优先队列元素。
若result为空列表则直接返回None。
"""
if result == []:
return None
else:
item, priority = result[0]
return {item: priority}
class PriorityQueue:
def __init__(self, client, key):
self.client = client
self.key = key
def insert(self, item, priority):
"""
将带有指定优先级的元素添加至队列,如果元素已存在那么更新它的优先级。
"""
self.client.zadd(self.key, {item: priority})
def remove(self, item):
"""
尝试从队列中移除指定的元素。
移除成功时返回True,返回False则表示由于元素不存在而导致移除失败。
"""
return self.client.zrem(self.key, item) == 1
def min(self):
"""
获取队列中优先级最低的元素及其优先级,如果队列为空则返回None。
"""
result = self.client.zrange(self.key, 0, 0, withscores=True)
return none_or_single_queue_item(result)
def max(self):
"""
获取队列中优先级最高的元素及其优先级,如果队列为空则返回None。
"""
result = self.client.zrange(self.key, -1, -1, withscores=True)
return none_or_single_queue_item(result)
def pop_min(self):
"""
弹出并返回队列中优先级最低的元素及其优先级,如果队列为空则返回None。
"""
result = self.client.zpopmin(self.key)
return none_or_single_queue_item(result)
def pop_max(self):
"""
弹出并返回队列中优先级最高的元素及其优先级,如果队列为空则返回None。
"""
result = self.client.zpopmax(self.key)
return none_or_single_queue_item(result)
def length(self):
"""
返回队列的长度,也即是队列包含的元素数量。
"""
return self.client.zcard(self.key)
以下代码展示了上述优先队列程序的具体使用方式:
>>> from redis import Redis
>>> from priority_queue import PriorityQueue
>>> client = Redis(decode_responses=True)
>>> queue = PriorityQueue(client, "PriorityQueue")
>>> queue.insert("Job A", 100) # 元素入队
>>> queue.insert("Job C", 200)
>>> queue.insert("Job B", 250)
>>> queue.insert("Job E", 280)
>>> queue.insert("Job D", 330)
>>> queue.length() # 查看队列长度
5
>>> queue.max() # 查看优先级最高的元素
{'Job D': 330.0}
>>> queue.min() # 查看优先级最低的元素
{'Job A': 100.0}
>>> queue.pop_max() # 弹出优先级最高的元素
{'Job D': 330.0}
>>> queue.pop_min() # 弹出优先级最低的元素
{'Job A': 100.0}