(七)循环队列的基本函数实现

1.队列

队列:一种先进先出的线性表,为什么是先进先出呢?因为它删除元素是在队头,而插入元素是在队尾,就像这样:
在这里插入图片描述
我们每插入一个数据,队尾指针就向后移一位,每删除一个数据队尾指针就向前移动一位,如我们删除一个数据就得到下图:
在这里插入图片描述
得到:
在这里插入图片描述
但是这样我们会发现这样每次删除数据的时间复杂度就是O(n),那么有没有什么好的方法让它变得更快一点呢?
这就出现了循环队列:

2.循环队列

循环队列不一样的地方就在于:

  1. 删除元素时不移动队尾指针,而是将队头指针向后移一位,这样大大提高了时间复杂度。
  2. 防止删除元素后前面空间的浪费,使用取模运算使队列抽象为循环队列,这里他不是存储空间链接起来,只是我们将它物理结构抽象为循环队列。
    在这里插入图片描述
    如下图,如果我们继续插入新的元素:
    在这里插入图片描述

3.关键点

下面我将说明几个关键的代码实现,先引入两个指针:front指向队头,rear指向队尾,
1.判断队列为空和队列是否已满:
我们发现:当队列为空时:front和rear指向同一个位置,但是当队列已满的时候,还是一样的情况,这要怎么办呢?
这时就出现了一个巧妙的解决方法:空出一个单元区分队列满了和空的状态,如下图:
在这里插入图片描述
我们可以看到,上图中队列满了有两种情况,而队列空就可以用front和rear是否相等来判断。假设队列的最大容量为:MAXSIZE,我们就可以用:(rear+MAXSIZE-front)%MAXSIZE == 0来判断队列是否已经满了。

代码

费了这么多话,下面就直接上代码了
头文件:

#define MAXSIZE 10
#define OK 1
#define ERROR 0

typedef int QElemType;
typedef struct {
	QElemType data[MAXSIZE];
	int front;
	int rear;
}SqQueue;

int InitQueue(SqQueue* Q);//初始化操作,建立一个空队列
int DestroyQueue(SqQueue *Q);//若队列存在,则销毁他
int ClearQueue(SqQueue *Q);//将队列Q清空
int QueueEmpty(SqQueue *Q);//若队列为空,返回true,否则返回flase
int GetHead(SqQueue Q,QElemType *e);//若队列存在且非空,用e返回队列Q的队头元素
int EnQueue(SqQueue* Q, QElemType e);//若队列Q存在,插入新元素E到队列Q中并成为队尾元素
int DeQueue(SqQueue* Q, QElemType* e);//删除队列Q中队头元素,并用e返回其值
int QueueLength(SqQueue *Q);//返回队列Q的元素个数

放函数的文件(有几个函数的代码就交给你们完成啦(主要是懒得写了,狗头保命嘿嘿)):

#include "head.h"

int InitQueue(SqQueue* Q) {
	Q->front = 0;
	Q->rear = 0;
	return OK;
}
int DestroyQueue(SqQueue* Q) {
	return 0;
}
int ClearQueue(SqQueue* Q) {
	return 0;
}
int QueueEmpty(SqQueue* Q) {
	if (Q->front == Q->rear)
		return OK;
	return ERROR;
}
int GetHead(SqQueue Q, QElemType* e) {
	return 0;
}
int EnQueue(SqQueue* Q, QElemType e) {
	if ((Q->rear + 1) % MAXSIZE == Q->front) {
		return ERROR;
	}
	Q->data[Q->rear] = e;
	Q->rear = (Q->rear + 1) % MAXSIZE;
	return OK;
}
int DeQueue(SqQueue* Q, QElemType* e) {
	if (Q->front == Q->rear)
		return ERROR;
	*e = Q->data[Q->front];
	Q->front = (Q->front + 1) % MAXSIZE;
	return OK;
}
int QueueLength(SqQueue *Q) {
	return (Q->rear + MAXSIZE - Q->front) % MAXSIZE;
}

主函数:

#include "head.h"
#include <stdio.h>
#include <stdlib.h>

int main(void) {
	SqQueue Q;
	QElemType data;
	InitQueue(&Q);

	scanf_s("%d",&data);
	while (data) {
		if (EnQueue(&Q, data) == ERROR) {
			printf("\n队列已满!\n");
			return -1;
		}
			
		scanf_s("%d", &data);
	}

	while (DeQueue(&Q, &data) == OK) {
		printf("data:%d\n", data);
	}
	return 0;
}

这里就是一个简单的入队列出队列,当然怎么能少了测试结果呢:
在这里插入图片描述
大家可以看到:1是最先入队列的,1也是最先出队列的,这就是先进先出了
在这里插入图片描述
因为我们空出了一个单元,我们的MAXSIZE设置的是10,所以在进入第十个元素的时候就报错了。

总结

荒废了将近一个周,害,重新振作,重新加油吧,冲冲冲!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小光学嵌入式

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

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

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

打赏作者

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

抵扣说明:

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

余额充值