一,基础概念
队列是由同一种数据元素组成的线性表结构。使用单向队列时,插入元素在一端进行而删除元素在另一端进行。
插入元素的一端在队列尾部(rear),删除元素的一端在队列头部(front)。新的数据元素不断从尾部进入队列,然后一直向前移动到头部。
队列与栈的结构相反,遵循的是先进先出(FIFO)原则。
队列结构在生活中的抽象模型有:售票口的排队队伍,打印机中一堆待打印的材料,它们都是先进先出的。
二,队列的图示结构
1.顺序队列,按照顺序结构进行存储,类似于数组
2.顺序队列的假溢出问题
对于顺序队列,不断的出队和入队操作,会让队列尾部的指针一直后移(rear=rear+1),直到超出队列的内存空间,此时,队列的存储空间还没被占满。队列的存储元素还没占满整个空间,队列的指针却发生了溢出,此现象被称为假溢出。为了避免假溢出问题,开发者更多时候使用特殊的顺序队列——循环队列。
3.特殊的顺序队列——循环队列
4.链式队列,按照链式结构进行存储,类似于链表
分别将元素12,24,36添加到队列,效果如图所示
三,队列的常见操作
Queue:初始化,创建一个空队列
enqueue:入队,在队列尾部添加一个元素
dequeue:出队,从队列头部移除一个元素,并返回
isEmpty:检查队列是否为空
size:返回队列中元素的数目
四,代码实现
注意,循环队列底层采用的是数组结构,链式队列底层采用的是单链表结构,因此,循环队列需要初始化队列的大小,即数组大小,而链式队列不需要。
1.循环队列的代码实现
循环队列在内存结构上还是一个普通数组,但是从抽象理解上,我们应该把它看作是一个头尾相连的环,通过取模运算来移动下标。
取模运算让队尾和队头的下标一直都在数组的地址空间以内移动,不会发生溢出。
假设循环队列的大小设置为maxSize
a.队尾下标往前移动一个单位:
rear = (rear + 1) % maxSize
b.队头下标往前移动一个单位:
front = (front + 1) % maxSize
c.判断队列是否为空:
front == rear(队尾和队头在同一个起点)
d.判断队列是否已满:
(rear + 1) % maxSize == front(队尾继续往前移动一个单位就可以和队头汇合)
Demo1.初始化
初始化时,顺序队列和循环队列的代码表示方式是一样的。主要初始化数组的大小、队头和队尾的初始值。
Python代码实现:
class CircularQueue():
def __init__(self, k):
self.k = k
self.queue = [None] * k
self.head = -1
self.tail = -1
C++代码实现: