数据结构-循环队列

        队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表,就是 一种先进先出(First In,First Out)的线性表,简称FIFO。因为其特殊性,在没用链表队列的情况下,也就是顺序存储,用两个变量来记录队列头和队列尾,一端记录出列(front),一端记录入列(rear),正常情况下它的数据长度会在front的更新下不断变小,当队列已满的情况下,rear指向的位置也不能在更新了。

        rear再往外就是非法内存了,队列这样肯定不行,就跟坐公交车一样,你上来的晚,后面没位置了,前排还有一个位置,你就不坐了,那也不可能啊。所以把队列想象成公交车一样,前排坐完坐后排,后排坐完前排有空位就坐前面。所以,循环队列就秉着不浪费资源的前提下诞生了。

 我们把队列的这种头尾相接的顺序存储结构称为循环队列。这队列还是那么大,但是再出列的时候,空出来的位置又可以入列了。

        这时候,又有一个问题了,怎么判断队列空和队列满,因为队列满和队列空front和rear在同一个位置,这就使我们不知道队列是空还是满了,所以我们怎么判断队列是空还是满呢?

办法一就是设置标志位,当front = rear ,flag = 0时,队列为空,当front = rear,flag = 1时,队列满。办法二,就是我们自己更新队满条件,当front = rear时,队列为空。当队列满时,保留一个元素空间,也就是队列虽然还剩下最后一个空闲单元,但也是满的。

主要来说一下方法二,队列满的时候,rear绕了整整一圈,设队列最长长度为MAX_QUEUE,(rear + 1)% MAX_QUEUE == front,取余就是为了避免rear 和front谁大谁小的问题。队列中的元素个数就是rear-front+MAX_QUEUE(对着图比比就出来了)。

//创建一个循环队列
//队列为空:rear == front
//队列为满:(rear + 1)%MAX_QUEUE = front
//front和rear更新方法
//front = (front + 1) % MAX_QUEUE
//rear  = (rear + 1) % MAX_QUEUE

想通就好了

数据类型:

#define MAX_QUEUE 10   //队列的最长长度

typedef int DataType;
typedef struct Queue
{
	DataType buf[MAX_QUEUE];  //队列长度
	int front;   //队列头的位置
	int rear;    //队列尾的位置
}SqQueue;

 代码如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_QUEUE 10   //队列的最长长度

typedef int DataType;
typedef struct Queue
{
	DataType buf[MAX_QUEUE];  //队列长度
	int front;   //队列头的位置
	int rear;    //队列尾的位置
}SqQueue;

//创建一个空的队列,并初始化
SqQueue *InitQueue()
{
	SqQueue *Q = (SqQueue *)malloc(sizeof(SqQueue));  //在堆区申请地址空间
	if(NULL == Q)
	{
		return NULL;

	}

	memset(Q, 0, sizeof(SqQueue)); //初始化
	Q->front = 0;   //新的队列,front 和 rear 都是0,表示这个队列是空的
	Q->rear = 0;
	return Q;
}

//判断队列是否为空
int Is_empty_Queue(SqQueue *Q)
{
	return Q->front == Q->rear ? 1 : 0;  //判断队列是否为空的条件是Q->front == Q->rear
}

//判断队列是否满
int Is_full_Queue(SqQueue *Q)
{
	return (Q->rear + 1)%MAX_QUEUE == Q->front ? 1 : 0; //判断队列是否满了条件是(Q->rear + 1) % MAX_QUEUE = Q->front
}

//入队列
void Push_Queue(SqQueue *Q, DataType data)
{
	if(Is_full_Queue(Q))
	{
		printf("队列为满\n");
		return ;
	}

	Q->buf[Q->rear] = data; //将数据放在rear的位置上
	Q->rear = (Q->rear + 1) % MAX_QUEUE;  //更新rear 
	return ;
}

//出队列
void Pop_Queue(SqQueue *Q, DataType *data)
{
	if(Is_empty_Queue(Q))
	{
		printf("队列为空\n");
		return ;
	}

	*data = Q->buf[Q->front];  //将front位置的数赋给*data
	printf("出队列的数是:%d\n",*data);
	Q->front = (Q->front + 1) % MAX_QUEUE;  //更新front
	return ;
}
//返回Q的元素个数
int QueueLength(SqQueue *Q)
{
	return (Q->rear - Q->front + MAX_QUEUE)%MAX_QUEUE;
}

//将队列清空
void ClearQueue(SqQueue *Q)
{
	while(Q->front != Q->rear)
	{
		Q->front++;
	}
}
//队列内容输出
void Printff_Queue(SqQueue *Q)
{
	if(!Is_empty_Queue)
	{
		printf("队列已空\n");
	}
	int i = Q->front;
	while(i % MAX_QUEUE != Q->rear)
	{
		printf("%d ",Q->buf[i]);
		i++;
	}
	putchar('\n');
}

int main()
{
	SqQueue *Q = InitQueue();
	char buf[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
	for(int i = 0;i < 10;i++)
	{
		Push_Queue(Q, buf[i]);
	}
	Printff_Queue(Q);

	int len = QueueLength(Q);
	printf("len = %d\n", len);

	int data = 0;
	Pop_Queue(Q,&data);
	printf("data:%d\n", data);
	Pop_Queue(Q,&data);
	printf("data:%d\n", data);

//	ClearQueue(Q);
	Printff_Queue(Q);
	return 0;
}

运行结果:

 

 因为队列大小为10,满的时候空一个,所以9就没压进去。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

焦不得

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值