Python用列表实现栈,队列(二)

用列表实现队列

       队列和栈实现的功能差不多,无非是入队列,出队列,队列长度等等。其中,入队列可以用列表的append()来实现,出队列可以使用pop(0)来实现。由于这个实现方法比较简单,因此它也是最低效的。append方法入队列和栈实现分析的一样,每次添加元素都有可能要换底层数组,所以效率不高;pop(0)操作的调用总是最坏情况,因为第一个元素移除,后面的所有元都需要往前移一位。
       对于append的低效,我们可以用改进栈的方法来改进队列实现:具体参考Python用列表实现栈,队列(一)。而对于pop(0)的低效,我们可以用空的指针来代替移除的元素,这样后面的元素就不会往前移动。但是这样的操作也有缺点:随着队列的使用,底层数组的大小会增长到 m m m m 是从队列创建以来所有添加到队列的元素(前面都是空指针),这样会占用大量的内存。对此,我们可以循环使用数组来解决:假设默认队列大小为 N N (索引为 0 N 1 0-N-1 ),并设_front为队列第一个元素的索引,_size为当前队列的大小。

  • 入队列操作:给索引为(_front+_size)% N N 赋值;
  • 出队列操作:给索引为_front赋值为None,并且第一个元素的索引后移一位:(_front+1)% N N
    具体程序如下:
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 ( 1 ) Q(1)^*
Q.dequeue() Q ( 1 ) Q(1)^*
Q.first() Q ( 1 ) Q(1)
Q.is_empty() Q ( 1 ) Q(1)
len(Q) O ( 1 ) O(1)

* 摊销

以上是Python列表实现的队列,如有错误,欢迎指教

猜你喜欢

转载自blog.csdn.net/zhisuihen6347/article/details/84480622
今日推荐