Python用列表實現棧,佇列(二)
阿新 • • 發佈:2018-11-25
用列表實現佇列
佇列和棧實現的功能差不多,無非是入佇列,出佇列,佇列長度等等。其中,入佇列可以用列表的append()來實現,出佇列可以使用pop(0)來實現。由於這個實現方法比較簡單,因此它也是最低效的。append方法入佇列和棧實現分析的一樣,每次新增元素都有可能要換底層陣列,所以效率不高;pop(0)操作的呼叫總是最壞情況,因為第一個元素移除,後面的所有元都需要往前移一位。
對於append的低效,我們可以用改進棧的方法來改進佇列實現:具體參考Python用列表實現棧,佇列(一)
- 入佇列操作:給索引為(_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列表實現的佇列,如有錯誤,歡迎指教