Python 队列


本文将简单阐述一下Python数据结构中队列的原理即实现方式。
首先我们来看一下,什么是队列:
队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。队列是一种先进先出(First in First Out)的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为队头。假设队列是q=(a1,a2,…,an),那么a1就是队头元素,而an是队尾元素。这样我们就可以删除时,总是从a1开始,而插入时,列在最后。这也比较符合我们通常生活中的习惯,排在第一个的优先出列,最后来的当然在队伍的最后。
****
如上图所示,队列是一种先进先出的线性表,我们用 front 表示队首,rear 表示队尾,但是在实际的运用过程中,往往会出现一种“假溢出”现象。
那么什么是假溢出现象呢?可以理解为系统作为队列用的存储区还没有满,但队列却发生了溢出,我们把这种现象称为”假溢出”。
****
如上图所示,在队列我的front指针指向的是第一个元素对应的位置,rear指针指向的是最后一个元素所对应的下一个元素位置。
****
如上图所示,当我一出了a1,a2后,front指针也同时移动到了a3的位置,可是,由于队列只有五个元素的长度,当a5进队列后,rear指针无处可指,同时,我们还发现,队列中还存在着两个位置的空位,这就是这个队列的假溢出现象,那么为了解决这一问题,人们想到了一个新的存储方式—-循环队列。所谓循环队列,就是将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列(Circular Queue)。循环队列是把顺序队列首尾相连,把存储队列元素的表从逻辑上看成一个环,成为循环队列。
****
如上图所示,就是一个循环队列的基本流程,但是,大家一定也发现了一个问题,为什么我们没有办法判断是否是队满还是队空呢?其实可以根据我们最原始的队列来看,如果front和rear指针相遇在一起,则证明这该队列是空队列,在循环队列中,当最后一个空间存入后,rear后移很容易与front指针再次相遇,因此,我们采取了牺牲一个存储空间的方式,来判断队满和队空。因此哦我们可以得到以下两个计算公式:
队列满的条件是:

(rear+1)%QueueSize == front

通用的计算队列长度的公式为:

(rear - front+ QueueSize)%QueueSize

那么我们要如何实现队列呢,当然可以使用列表,但是本文采用类的方式为大家实现一下队列的原理:

class Queue:  
    def __init__(self,size = 100):  # 对队列进行初始化操作
        self.queue = [0 for i in range(size)]  
        self.size = size              
        self.rear = 0                  # 设定头指针和尾指针都为0号元素,此时队空
        self.front = 0   

    def push(self, element):          # 定义入队操作
        if not self.is_filled():      # 如果队不满
            self.rear = (self.rear + 1) % self.size # 队尾指针应指向最后元素的下一地址  
            self.queue[self.rear] = element          # 将该元素放入队列
        else:  
            raise IndexError("Queue is filled.")      # 反之则证明队满,告诉用户不要进了

    def pop(self):  
        if not self.is_empty():      # 如果队不空
            self.front = (self.front + 1) % self.size    # 队首指针指向下一元素  
            return self.queue[self.front]                # 返回队首元素  
        else:                                           
            raise IndexError("Queue is empty.")        # 反之证明队空,则无元素可出


    def is_empty(self):              # 定义队空,是两指针相等时
        return self.rear == self.front  

    def is_filled(self):              #定义队满,按照上文公式
        return (self.rear + 1) % self.size == self.front

这就是整手写的队列过程。其实,在Python中并不需要这么麻烦,众所周知,Python是一门集百家所长的语言,我们可以import一个对自己有用的类库,譬如说 deque 这个类库。
首先进行一波引用:

from collections import deque

该类库的特点就是已经帮我们写好了队列的这个类以及其中的成员函数,其中我们主要会用到如下这四个函数:

   deque.append()        # 右侧进队
   deque.pop()            # 右侧出队
   deque.popleft()        # 左侧出队
   deque.appendleft()    # 左侧进队

以上就是Python队列的大致原理及其特有类库,各位看官有何不懂之处,欢迎在评论区留言。


文章作者: Runze_Li
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Runze_Li !