首先说一下主要思路:循环队列的关键就是区别队列满和空的
两个条件,因为是循环队列,空和满状态会是相同的!至于循环方式可以采用一个空闲单位的方式(x+1)%MaxSize,+1其实就浪费了MaxSize-1索引存储的数据。好了不多说看下写法吧!
下面展示一下第一种写法
。
第一种写法,比较普遍,这就是空闲单位法
思路:留一个空间作为区别队列空和满的判定
#include <stdio.h>
#define MaxSize 6
#define DataType int
typedef struct{
DataType data[MaxSize];
int front;
int rear;
}SeQueue;
void InitSeQueue(SeQueue *q){
q->rear=q->front=0;
}
int EnQueue(SeQueue *q,int x){
if(q->front==(q->rear+1)%MaxSize)
/*这里判定条件说明一下,首先目的是为了防止超出队列空间。
其次这个公式意思就是尾部到末尾再加上一正好回到起点,
说明队满了。但这时浪费了一个位置就是MaxSize-1的这个位置,
用来判断队满了!而如果采用队列为空q->front==q->rear来判
断是否超出队列是不行的,因为队为空和队满都是一样的条件,
会引起歧义。
*/
return false;
else{
q->data[q->rear]=x;
q->rear=(q->rear+1)%MaxSize;//rear指向下一个位置,由于是循环可能超出上限所以采用这个公式。
return true;
}
}
int DeQueue(SeQueue *q,int &x){
if(q->front==q->rear)//说明队列为空
return false;
else{
x=q->data[q->front];
q->data[q->front]=0;
q->front=(q->front+1)%MaxSize;//同理
return true;
}
}
int PrintSeQueue(SeQueue *q){
while(q->front!=q->rear){//判断队列是否为空的条件
printf("%d ",q->data[q->front]);
q->front=(q->front+1)%MaxSize;
}
}
int main(){
SeQueue q;
InitSeQueue(&q);//初始化
for(int i=0;i<=4;i++)
EnQueue(&q,i);//插入5个数
PrintSeQueue(&q);//输出5个数
}
下面展示一下 第二种写法
。
第二种写法,可以更好利用了第一种写法浪费的空间,标记法。
思路:既然第一种写法浪费了空间,那么要利用第一种写法浪费的空间,我们就可以利用
好第一种写法的判断队列满的判定条件q->front==(q->rear+1)%MaxSize,说明q->rear+1
结尾前一个的这个空间没有用到,那么我们就有一个思路了,标记一个flag,把这个空间
利用起来,让判定条件认为这个地方是可以放入队列成员的!判定完后,再设个条件作为
判定队列已满的条件flag=1,那么就有了两个区别队列空和满的条件了!重点:判断为空的
条件是:flag==0&&q->front==q->rear 为满的条件:flag==1
(如果有更好的想法欢迎在评论区提出,我会努力修改的!)
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 6
#define DataType int
int flag = 0;//0表示队列未满,默认为0,1表示队列已满。
typedef struct{
DataType data[MaxSize];
int front;
int rear;
}SeQueue;
void InitSeQueue(SeQueue *q){
q->rear=q->front=0;
}
int EnQueue(SeQueue *q,int x){
if(flag==1){
return false;//表示队列已满,无法插入。
}
if(q->front==(q->rear+1)%MaxSize){
/*
队列刚好到空闲的地方,插入后flag未0 ,表示已满!
*/
q->data[q->rear]=x;
q->rear=(q->rear+1)%MaxSize;
flag = 1;
return true;
}
if(flag==0){
/*队列未满,直接插入。注意:这个条件不能用||加入到上面,
否则flag后面直接=1就默认满了。
*/
q->data[q->rear]=x;
q->rear=(q->rear+1)%MaxSize;
return true;
}
}
int DeQueue(SeQueue *q,int &x){
if(q->front==q->rear&&flag!=1)//两个条件必须同时成立,说明队列为空!
return false;
else{
x=q->data[q->front];
q->data[q->front]=0;
q->front=(q->front+1)%MaxSize;
flag=0;//删除一个说明队列有空位置了
return true;
}
}
int PrintSeQueue(SeQueue *q){
int flag1=flag;
while(flag==1||q->front!=q->rear){
/*
说明队列为满或不为空
注意:不可以改为flag==0
因为队满的时候flag==1
*/
printf("%d ",q->data[q->front]);
q->front=(q->front+1)%MaxSize;
flag=0;
/*
把队列设为未满,是为了防止如果flag==1的话while一直循环下去!当然你
设置个if条件判断也可以。
*/
}
flag=flag1;//结束后flag设置原来状态
}
int main(){
SeQueue q;
int x;
InitSeQueue(&q);//队列初始化
for(int i=0;i<=5;i++)
EnQueue(&q,i);//进队六个数据
for(int i=0;i<=4;i++)
DeQueue(&q,x);//出队五个数据
PrintSeQueue(&q);//打印结果
}