用列表实现队列
队列和栈实现的功能差不多,无非是入队列,出队列,队列长度等等。其中,入队列可以用列表的append()来实现,出队列可以使用pop(0)来实现。由于这个实现方法比较简单,因此它也是最低效的。append方法入队列和栈实现分析的一样,每次添加元素都有可能要换底层数组,所以效率不高;pop(0)操作的调用总是最坏情况,因为第一个元素移除,后面的所有元都需要往前移一位。
对于append的低效,我们可以用改进栈的方法来改进队列实现:具体参考Python用列表实现栈,队列(一)。而对于pop(0)的低效,我们可以用空的指针来代替移除的元素,这样后面的元素就不会往前移动。但是这样的操作也有缺点:随着队列的使用,底层数组的大小会增长到
,
是从队列创建以来所有添加到队列的元素(前面都是空指针),这样会占用大量的内存。对此,我们可以循环使用数组来解决:假设默认队列大小为
(索引为
),并设_front为队列第一个元素的索引,_size为当前队列的大小。
- 入队列操作:给索引为(_front+_size)% 赋值;
- 出队列操作:给索引为_front赋值为None,并且第一个元素的索引后移一位:(_front+1)%
。
具体程序如下:
class Empty(Exception):
def __init__(self, m):
super().__init__(self)
self.message = m
def __str__(self):
return self.message
class ArrayQueue:
DEFAULT_CAPACITY = 10
def __init__(self):
self._data = [None] * self.DEFAULT_CAPACITY
self._size = 0
self._front = 0
def __len__(self):
return self._size
def is_empty(self):
return self._size == 0
def first(self):
if self.is_empty():
raise Empty('Queue is empty')
return self._data[self._front]
def dequeue(self):
if self.is_empty():
raise Empty('Queue is empty')
data = self._data[self._front]
self._data[self._front] = None
self._front = (self._front + 1) % len(self._data)
self._size -= 1
return data
def enqueue(self, e):
if self._size == len(self._data):
self._resize(2 * len(self._data))
index = (self._front + self._size) % len(self._data)
self._data[index] = e
self._size += 1
def _resize(self, cap):
old = self._data
self._data = [None] * cap
walk = self._front
for k in range(self._size):
self._data[k] = old[walk]
walk = (walk + 1) % len(old)
self._front = 0
测试程序:
from ArrayQueue import *
Q = ArrayQueue()
try:
print(Q.is_empty())
Q.enqueue(0)
Q.enqueue(1)
print(Q.first())
print(len(Q))
print(Q.dequeue())
print(Q.dequeue())
Q.dequeue()
Q.enqueue(1)
except Empty as e:
print(e)
测试结果:
以上代码中,_resize()方法是对列表的扩展,当然我们也可以添加一些代码,使其当存储元素降低到数组总存储能力的四分之一的时候,列表容量缩小到当前的一半。(和之前Python列表实现栈一样)
if self._size <= len(self._data)/4
self._resize(len(self._data)//2)
最后总结一下Python列表实现的队列的效率:
操作 | 运行时间 |
---|---|
Q.enqueue(e) | |
Q.dequeue() | |
Q.first() | |
Q.is_empty() | |
len(Q) |
* 摊销
以上是Python列表实现的队列,如有错误,欢迎指教