循环队列操作 C

队列的出入条件  是先进先出,就是队头出,队尾入,根据这个特性,我们可以用两个指针来代表队头的位置与队尾的位置,队头为front,队尾为 rear。

我们假设一个长度为5的数组,来模拟队列:

这时 rear和front 指针都指向 下标0的位置,所以我们判断队列为空时,就是当 rear指针==front指针。然后让a1,a2,a3,a4 入队,如图:
在这里插入图片描述
所以当a1,a2,a3,a4入队时,front指针不动,让rear指针依次指向下一个下标,这时rear指针则指向下标4,这时我们在进行出队操作,让a1,a2出队。如图:
在这里插入图片描述
我们可以看到 a1,a2出队时,rear指针不动,front指针依次指向下一个下标,这时front指针指向 下标2;这时我们再插入a5,如图
在这里插入图片描述
这时我们的rear 已经指向了数组的外面,所以已经代表无法入队了,但我们可以看到队列中的个数并没有超过5个,但是以及无法进行入队操作,这种情况,我们通常叫做“假溢出”,所以,像这种顺序队列 十分容易照成“假溢出”的情况,这样空间利用率大大减小。
所以我们要怎么解决这种情况呢? 我们可以将rear 指针在数组外面的时候在指向头,就是头尾相连的循环。如图:
在这里插入图片描述
我们将rear 指针指向下标0,这样我们就不会出现指针指向不明,而且可以解决“假溢出”的情况。这是我们将 a6,a7入队,如图:
在这里插入图片描述
这时我们的rear指针指向下标 2,这个时候我们可以看到我们的rear指针与front指针 都为2,这时相等。 所以队满的情况为 rear == front,但是我们判断队空的条件也是 rear = = front,所以我们无法区分当rear=front的时候,是队空还是队满。
所以我们将队空的条件保持不变为rear = front ,并且当队列满时,我们改变条件,当队列还剩一个空间时 判断为队满,就是当队满的时候,数组还剩一个单元。如图;
在这里插入图片描述
这种情况我们就判断为队满。
但是,我们可以看出有时 rear>front,有时front>rear,所以我们并不好计算队满的条件。然后队列的最大长度为 Max_size,即我们可以判断队满的条件可以为 (rear + 1) % Max_size == front ,这样不管rear是否比front大,都可以判断。
这时我们就可以开始模拟代码了:

#define Max_size 100
typedef struct
{
	int *data;
	int front;//头指针
	int rear;//尾指针
}SqQueue;

1.初始化

int InitQueue(SqQueue& q)//初始化空队列
{
	q.data = (int*)malloc(sizeof(int) * Max_size);//动态分配空间
	if (!q.data)//如果分配失败,则停止程序
		exit(0);
	q.front = 0;
	q.rear = 0;
	return 1;
}//当 rear == front时,队列判断为空

2.入队

int EnQueue(SqQueue& q, int e)//插入,e为插入的值
{
	if ((q.rear + 1) % Max_size == q.front)//当 rear 的下一个指标指向front的时候就代表队列满了
		return 0;
	q.data[q.rear] = e;//将e赋予队尾
	q.rear = (q.rear + 1) % Max_size;//将rear指针后移一位。  如果是末尾的话则转到数组头部
	return 1;
}

3.出队

int DeQueue(SqQueue& q, int* e)//删除队头元素,e为返回的值
{
	if (q.rear == q.front)//判断队列是否为空
	{
		return 0;
	}
	*e = q.data[q.front];
	q.front = (q.front + 1) % Max_size;//将front指针后移一位。  如果是末尾的话则转到数组头部
	return 1;
}

4.销毁队列

int DestroyQueue(SqQueue& q)//销毁队列
{
	if (q.data)//如果q.data不为空,则释放
	free(q.data);
	q.data = NULL;
	q.rear = q.front = 0;
	return 1;
}

5.求队列长度

int QUeueLength(SqQueue q)//求队列长度
{
	return (q.rear - q.front + Max_size) % Max_size;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值