队列(Queue):和栈一样,也是一种操作受限的线性表,但它只允许在表的一端进行插入,在另一端进行删除。操作特征是先进先出(FIFI,First In First Out)
队头(Front):允许删除的一端,又称为队首
队尾(Rear):允许删除的一端
空队列:不含有任何元素的空表
在这里插入图片描述

队列常见操作:
IniQueue():初始化队列,构造一个空队列
isempty():判空
isfull():判满
EnQueue():若队列未满,从队尾入队
DeQueue():若队列非空,从队首出队
GetHead():获取队首元素
顺序队列:
分配一块连续的存储单元,并附带两个指针front和rear分别指示队首元素和队尾元素,一般队首指针指向队首元素,队尾指针指向队尾元素的下一个位置。
在这里插入图片描述

class myQueue():

    def __init__(self, size):#初始化一个空队列
        self.size = size
        self.front =0
        self.rear = 0
        self.queue = []

    def enqueue(self, x):  # 入队操作
        if self.isfull():
            print("queue is full")
            return False
        else:
            self.queue.append(x)
            self.rear = self.rear + 1
            return True

    def dequeue(self):  # 出队操作
        if self.isempty():
            print("queue is empty")
            return False
        else:
            duiwei = self.queue[self.front]
            self.queue.pop(self.front)
            return duiwei

    def isfull(self):
        return self.rear - self.front + 1 == self.size
    def isempty(self):
        return self.front == self.rear

    def gethead(self):
        if self.isempty():
            return False
        else:
            return self.queue[self.front]

    def show(self):
        print(self.queue)

qq= myQueue(10)
print("初始化队列为空",qq.isempty())

for i in range(10):
    qq.enqueue(i)
qq.show()
print("插入十个元素后,队满",qq.isfull())
print(qq.dequeue())
print(qq.dequeue())
print(qq.dequeue())
print(qq.dequeue())




输出为:

初始化队列为空 True
queue is full
[0, 1, 2, 3, 4, 5, 6, 7, 8]
插入十个元素后,队满 True
0
1
2
3

需要注意的地方:
1)初始状态(队列为空):front==rear=0
2)入队:队不满时,先送值到队尾元素,然后rear加1
3)出队:队非空时,先取队首元素的值,然后front加1
4)不可以用"rear=size"来判断队列是否为满,上图(d)也满足"rear=size",但不是队列为满,这是一种假溢出。

循环队列
顺序队列存在缺点,元素出队后该位置就空着而没有被利用,最终造成假溢出,新的元素也无法入队。使用循环队列来解决这个问题:即把存储队列元素的表从逻辑上看作一个环。
在这里插入图片描述

初始时:front=rear=0
出队时:front=(front+1)%size
入队时:rear=(rear+1)%size
元素个数:(rear+size-front)%size
队空的条件:rear=front
队满的条件:rear=front,如图所示,将会导致无法判断队空或者队满。
三种方式来区分队空还是队满:
1)牺牲一个单元,入队时少用一个队列单元,即队列的元素个数最大为size-1
元素个数:(rear+size-front)%size
队空的条件:rear=front
队满的条件:(rear+1)%size=front
2)队列增加一个元素个数的数据成员,elenum=0时队列为空,elenum=size时队列为满。
3)类型中增加一个tag数据成员,出队导致rear=front,tag=0,表示队空;入队导致rear=front,tag=1,表示队满
第一种方式的代码实现如下:

class myCycleQueue():
    def __init__(self,size):  #初始化
        self.rear=0
        self.front=0
        self.size=size
        self.queue=[]
    def isempty(self): #判空
        return True if self.front==self.rear else False
    def isfull(self): #判满
        return True if (self.rear+1)%self.size==self.front else False
    def elenum(self): #获取元素个数
        return (self.rear + self.size - self.front)%self.size
    def enqueue(self,x): #入队
        if self.isfull():
            print("queue is full")
            return False
        else:
            self.queue.append(x)
            self.rear=(self.rear+1)%self.size
    def dequeue(self): #出队
        if self.isempty():
            print("queue is empty")
            return False
        else:
            x=self.queue[self.front]
            self.front=(self.front+1)%self.size
            self.queue.pop(self.front)
            return x

链队列:
同时带有队头指针和队尾指针的单链表,头指针指向队头节点,队尾指针指向队尾结点。
在这里插入图片描述

class Node:
    def __init__(self, value):
        self.value = value
        self.next = None

class Queue:
    def __init__(self):
        self.front = None  # 队头指针
        self.rear = None   # 队尾指针

    def is_empty(self):
        return self.front is None

    def enqueue(self, value):
        new_node = Node(value)
        if self.is_empty():
            self.front = new_node
            self.rear = new_node
        else:
            self.rear.next = new_node
            self.rear = new_node

    def dequeue(self):
        if self.is_empty():
            raise Exception("Queue is empty")
        else:
            value = self.front.value
            self.front = self.front.next
            if self.front is None:
                self.rear = None
            return value

    def peek(self):
        if self.is_empty():
            raise Exception("Queue is empty")
        else:
            return self.front.value

# 创建一个示例队列
queue = Queue()

# 入队操作
queue.enqueue(1)
queue.enqueue(2)
queue.enqueue(3)

# 出队操作
print(queue.dequeue())  # 输出: 1
print(queue.dequeue())  # 输出: 2

# 获取队头元素
print(queue.peek())     # 输出: 3

定义了一个 Node 类,表示链队列的节点,每个节点包含一个 value 值和一个 next 指针指向下一个节点。
定义了一个 Queue 类,表示链队列,其中包含 front 和 rear 两个指针,分别指向队列的头部和尾部。初始时,这两个指针都为空。
is_empty 方法用于判断队列是否为空,如果 front 为空,则队列为空。
enqueue 方法用于入队操作,创建一个新的节点,并根据队列是否为空来更新 front 和 rear 指针。
dequeue 方法用于出队操作,从队列的头部移除一个节点,并更新 front 指针。如果移除后队列为空,则同时更新 rear 指针。
peek 方法用于获取队头元素,即返回 front 指针指向的节点的值。
通过这种方式,实现了链队列的基本功能,包括入队、出队和获取队头元素等操作。链队列的入队和出队操作都能够在 O(1) 的时间复杂度内完成。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐