循环队列的两种写法

首先说一下主要思路:循环队列的关键就是区别队列满和空的
两个条件,因为是循环队列,空和满状态会是相同的!至于循环方式可以采用一个空闲单位的方式(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);//打印结果
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值