队列:只允许在一端进行插入操作,另一端进行删除操作的线性表。
队头:允许删除的一端
队尾:允许插入的一端
入队:队列的插入操作
出队:队列的删除操作
队列的顺序存储结构:因为如果限定队头在数组下标0的位置,则删除队头是,后面的元素都要向前移动一位,所以可以引入两个指针front指向队头元素,rear指向队尾元素的下一位。
则当front==rear时,队列为空。
若图中队列在插入一个元素a4,则rear指向哪里呢?这里就可以引入循环队列了。
循环队列:头尾相接的顺序存储结构的队列。
所以插入a4后rear指向下标0,当再插入a5后,队列满了,front又等于rear了。那应该如何区别队列为空还是队列满的情况呢?
方法一:
这时候可以设置一个变量flag,当front==rear且flag==0时,队列为空。当front==rear且flag==1时,队列满了。
方法二:
可以规定只剩下一个空间(或位置)时,队列满了。因为队列满时rear的下一个一定是front,所以可以用%来实现,(rear+1)%arr.size()==front来判断队列是否满了。有两种情况:
此时队列满了,rear==4,front==0,arr.size()==5,所以有(4+1)%5==0,队列满。
第二种情况:
此时队列满了,rear==1,front==2,arr.size()==5,所以有(1+1)%5==2,队列满。
当队列的rear>front时,队列的长度为rear - front,比如第一种情况,队列长度为4-0=4。
当队列的rear<front时,队列的长度为arr.size() - front+rear,比如第二种情况,5-2+1=4。
所以队列的长度计算公式为:
(rear - front+arr.size())%arr.size()
循环队列的顺序存储结构代码:
typedef struct {
type data[Max];
int front;
int rear;
}SqQueue;
循环队列的初始化:
struct InitQueue(SqQueue *Q)
{
Q->front=0;
Q->rear=0;
return OK;
}
求循环队列的长度的函数:
int QueueLength(SqQueue *Q)
{
return (Q.rear - Q.front+Max)%Max;
}
队列的入队函数:
Status EnQueue(SqQueue *Q , type *e)
{
if((Q->rear+1)%Max==Q->next)
return ERROR; // 判断队列是否满了
Q->data[Q->rear]=e; // 把e赋给rear
Q->rear=(Q->rear+1)%Max; // rear++
return OK;
}
队列的出队函数:
Status EnQueue(SqQueue *Q , type *e)
{
if(Q->front==Q->rear) //判断队列是否为空
return ERROR;
*e=Q->data[Q->front]; // 把队头元素赋给e
Q->front=(Q->front+1)%Max; // front++;
return OK;
}