队列也是一种线性结构,不同于栈的是队列为先进先出的数据结构,遵循一边入队一边出队。
顺序队列底层使用的是数组,所以需要提前申请足够大的内存空间来初始化顺序队列。另外,为了满足顺序队列中的数据从队尾进入,从队头退出,先进先出的要求,我们还需要定义两个指针(top和rear)分别指向顺序队列中的头元素和尾元素。尾部元素。
入栈的数据始终存储在数组中,但读取数据时,是从记录的第一个元素开始读取。
在添加(入队)时,元素被添加到队位(rear)所在位置,对位加一,依次类推,这样在添加元素时元素依次填充数组的位置。
#include<stdio.h>
#define MAXSIZE 5
typedef struct Queue{
int datas[MAXSIZE];
int front;
int rear;
}SqQueue;
//入队
int Push(SqQueue *S,int e){
if(S->rear == MAXSIZE) return 0;
S->datas[S->rear] = e;
S->rear++;
return 1;
}
//出队
int Pop(SqQueue *S){
int e = S->datas[S->front];
S->front++;
return e;
}
int main(){
SqQueue S;
S.front = S.rear =0;
Push(&S,3);
Push(&S,5);
Push(&S,7);
int e = Pop(&S);
printf("%d\n",e);
int e1 = Pop(&S);
printf("%d\n",e1);
int e2 = Pop(&S);
printf("%d\n",e2);
return 0;
}
删除(出队)时,队列头(top)指向的元素被赋给临时变量,队列头移回指向下一个元素。队头继续像光标一样记录当前位置,模拟元素出队。
对于数组实现的会遇到假溢出问题,如下:
当rear指向最后一个元素时,rear无法在后移,于是队列满了,但是看top的位置却在第4个元素的位置,也是说前三个元素都出栈了,空出了三个元素的位置。为了解决该假溢出的问题,可以将队列变成一个循环队列。
循环队列利用top,rear,MAXSIZE
的关系巧妙模拟循环。rear在指向最后一个位置时再次添加就回到数组第一个位置,再一次向后移,top也是如此。
如果是循环队列,则操作必须基于MAXSIZE。所以rear只能在[1, MAXSIZE]范围内。那么rear的操作就变成:
S->rear = (S->rear+1)%MAXSIZE
注意如果以mAXSIZE定义数组那么数组为
[MAXSIZE-1]
,因为数组是从0开始的。
如何判断队列是否已满?
- 第一种情况
主要有以上两种情况表示队列满了。第一种S->rear = (S->rear+1)%MAXSIZE
,注意是计算后的情况,满足Q.front = Q.rear
。这种判断是不合理的,因为该判断条件也是判空的条件。
一般情况下,可以少用一个元素空间。即当队列空间大小为m时,如果有m-1个元素则认为队列已满。这样,判断队列为空的条件保持不变,即头尾指针的值相同时,认为队列为空;当尾指针循环加1等于千个头指针时,认为队列已满。 (完美解决问题,无需放弃存储元件的空间)。
途中的后值是加入队列后计算的后值。
在少用一个元素的情况下,满足(S->rear+1)%MAXSIZE) == S->front
表示队满。
因此, 在循环队列中队空和队满的条件是:
队空的条件:Q.front = Q.rear
队满的条件:(Q rear+ 1)%MAXSIZE = Q.front
#include<stdio.h>
#define MAXSIZE 5
typedef struct Queue{
int datas[MAXSIZE];
int front;
int rear;
}SqQueue;
//入队
int Push(SqQueue *S,int e){
if( (S->rear+1)%MAXSIZE ==S->front) return 0;
S->datas[S->rear] = e;
S->rear = (S->rear+1)%MAXSIZE;
return 1;
}
//出队
int Pop(SqQueue *S){
int e = S->datas[S->front];
S->front = (S->front+1)%MAXSIZE;
return e;
}
int main(){
SqQueue S;
S.front = S.rear =0;
Push(&S,3);
Push(&S,5);
Push(&S,7);
int e = Pop(&S);
printf("%d\n",e);
int e1 = Pop(&S);
printf("%d\n",e1);
int e2 = Pop(&S);
printf("%d\n",e2);
return 0;
}
连锁团队是指采用链式存储结构实现的队列。和顺序队列一样链对也需要队头和队尾游标,并以链表为存储结构。链队就是后插法创建链表。