前言
这里,我们的优先级队列是涉及到了一个key-value对的,其中key是我们的优先级,value是对象。
首先介绍一下优先级队列吧,是一个应用范围比队列广很多的数据结构,其实用堆来做比较好,这部分介绍的是双向链表。
如果对双向链表有问题,看这里。
基本结构
首先给出一个基类
class PriorityQueueBase():
"""Abstract base class for a priority queue"""
class _Item():
"""lightweight composite to store priority queue items"""
__slots__ = '_key', '_value'
def __init__(self,k,v):
self._key = k
self._value = v
def __lt__(self,other):
# 这样就可以直接比较两个结点,而不需要比较key
return self._key < other._key
def is_empty(self):
"""retrun True if the priority queue is empty"""
return len(self)==0
很简单,内部有一个item的类存储每一个结点key、value,并重载了大小比较运算符,方便我们就行比较。
还有一个is_empty函数,都是常用的。
具体实现
这里的实现分为两种,排序列表和未排序列表。
顾名思义,就是我们存储的列表(其实是双向链表)是否有序,如果是无序列表,查找为O(n);如果有序,插入为O(n)。
直接贴代码,加上注释没什么问题:
# 未排序列表,查找删除代价大
class UnsortedPriorityQueue(PriorityQueueBase):
"""a min-oriented priority queue implemented with an unsorted list"""
def __init__(self):
"""Create a new empty Priority Queue"""
# 这个是双向链表
self._data = PositionalList()
def __len__(self):
"""return the number of items in the priority queue"""
return len(self._data)
def add(self,key,value):
"""add a key-value pair"""
# 双向链表的一个尾插法
self._data.add_last(self._Item(key,value))
def _find_min(self):
"""rturn position of item with minimum key"""
if self.is_empty():
raise Empty('Priority queue is empty')
small = self._data.first()
walk = self._data.after(small)
# 最小的初始为第一个,然后遍历(通过walk)
while walk is not None:
if walk.element() < small.element():
small = walk
walk = self._data.after(walk)
return small
def min(self):
"""return but do not remove (k,v) tuple with minimum key"""
p = self._find_min()
item = p.element()
return (item._key,item._value)
def remove_min(self):
"""remove and return (k,v) tuple with minimum key"""
p = self._find_min
item = self._data.delete(p)
return (item._key,item._value)
# 已排序列表,插入代价大
class SortedPriorityQueue(PriorityQueueBase):
"""a min-oriented priority queue implemented with a sorted list"""
def __init__(self):
"""create a new empty Priority Queue"""
self._data = PositionalList()
def __len__(self):
"""return the number of items in the priority queue"""
return len(self._data)
def add(self,key,value):
"""add a key-value pair"""
newest = self._Item(key,value)
walk = self._data.last()
# 有序,插入比较麻烦
while walk is not None and newest < walk.element():
walk = self._data.before(walk)
if walk is None:
self._data.add_first(newest)
else:
self._data.add_after(walk,newest)
def min(self):
"""return but noe remove (k,v) tuple with minimum key"""
if self.is_empty():
raise Empty('Priority queue is empty')
p = self._data.first()
item = p.element()
return (item._key,item._value)
def remove_min(self):
"""return and remove (k,v) with minimum key"""
if self.is_empty():
raise Empty('Priority queue is empty')
item = self._data.delete(self._data.first())
return (item._key,item._value)