目录
一、概述
1、队列ADT
队列(Queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
队列是一种先进先出(First In First Out)的线性表。
允许插入的一端称为队尾,插入数据的操作称为入队。
允许删除的一端称为队头,删除数据的操作称为出队。
2、队列的基本操作
CreatQueue() ——初始化队列
MakeQueueEmpty ——清空队列
EnQueue() ——进队列
DeQueue() ——出队列
IsQueueEmpty() ——判断队列是否为空
IsQueueFull() ——判断队列是否已满
3、队列的实现方式
队列可以由数组和链表两种形式实现队列操作。分别称为顺序队列和链队列。
且顺序队列还可以实现循环,已增加空间的利用。
下面均讨论顺序循环队列。
二、队列的数组实现
1、队列的结构
typedef struct QueueRecord {
int Capacity; //队列容积
int Front; //队头下标
int Rear; //队尾下标
int *array; //数据域
} *Queue, queue;
2、清空队列
这个很重要,为了方便起见,默认队列为空时,队头在0,队尾在-1。
每个人习惯不同,可以不一样(有的人会将初始队尾设置为0),但是后面的操作也要对应改变。
每当插入新的队列尾元素时,“尾指针增1”
每当删除队列头元素时,“头指针增1”。
因此,非空队列中,队头始终指向队列头元素,队尾始终指向队列尾元素(另:队尾指向队列末尾元素的下一个)。
void MakeQueueEmpty(Queue Q) {
Q->Front = 0;
Q->Rear = -1;
}
3、创建一个初始化队列
Queue CreatQueue (int MaxElement) {
Queue Q = (Queue)malloc(sizeof(queue));
Q->array = (int *)malloc(sizeof(int)*MaxElement);
Q->Capacity = MaxElement;
MakeQueueEmpty(Q); //初始化清空队列
return Q;
}
4、判断队列是否满
如何判断一个循环队列是否满的? 不如这样理解:
假设我们在军训中排队,每个人报数。一个队列只能站10个人,从1报到10,队就满了。后来呢,队头的两个人出队了,然后又补充了两个新队员,那么这时候的报数是3到12。这时队列也是满的。
两种情况下判断队满的条件分别为:
(10 + 1) % 10 = 1
(12 + 1) % 10 = 3
所以很容易发现队列满的条件就是 :
(rear+1) % Capacity == front
int QueueIsFull(Queue Q) {
return (Q->Rear + 1) % Q->Capacity == Q->Front;
}
5、入队
先要判断是否队列已满。
入队:队尾后移出一位并赋值。
需要注意的是,这里实现的时循环队列,所以当队尾移至超出数组下标界限时,要将其移至数组的开始,以实现循环储存。
void Enqueue(int x, Queue Q){
if (QueueIsFull(Q)) //队列已满
return;
if(++ Q->Rear == Q->Capacity) //队尾后移一位,若到数组末端,至于最前
Q->Rear = 0;
Q->array[Q->Rear] = x; //入队
}
6、判断队列是否为空
int QueueIsEmpty(Queue Q) {
return Q->Rear + 1 == Q->Front;
}
7、出队操作
注意不要对空队列进行出队操作,先要判断队列是否为空。
void Dequeue(Queue Q) {
if(QueueIsEmpty(Q))
return;
if (++Q->Front == Q->Capacity) //队首后移一位(相当于删除队首)
Q->Front = 0;
}
End
欢迎关注个人公众号“鸡翅编程”,这里是认真且乖巧的码农一枚,旨在用心写好每一篇文章,平常会把笔记汇总成推送更新~
来源:CSDN
作者:贝贝今天AC了吗
链接:https://blog.csdn.net/weixin_43787043/article/details/103940486