数据结构 栈与队列(三)循环队列

循环队列

实际中我们还会用到一种队列叫做循环队列,这种队列把存储空间前后连接起来,形成像环一样的结构,解决了内存空间浪费的问题
在这里插入图片描述
这里我们用顺序结构来实现,因为为了防止溢出的情况,这里我们需要多开一个数据的空间用作缓冲,这部分不用于存数据,用于防止溢出,当数组访问到这一部分时就将他归零,实现循环的结构。
每次入数据通过队尾指针入,出数据通过队首指针出,和队列的操作方法差不多,每一步骤的具体实现思路会在下面写出

数据结构
typedef int DataType;
typedef struct 
{
	DataType* queue;
	int front;
	int rear;
	int length;
} CircularQueue;
实现的接口
CircularQueue* CircularQueueCreate(int k);
//循环队列初始化
bool CircularQueueEnQueue(CircularQueue* obj, DataType value);
//循环队列入队
bool myCircularQueueDeQueue(CircularQueue* obj);
//循环队列出队
DataType CircularQueueFront(CircularQueue* obj);
//获取循环队列队首
DataType CircularQueueRear(CircularQueue* obj);
//获取循环队列队尾
int CircularQueueSize(CircularQueue* obj);
//循环队列长度
bool CircularQueueIsEmpty(CircularQueue* obj);
//判断循环队列是否为空
bool CircularQueueIsFull(CircularQueue* obj);
//判断循环队列是否已满
void CircularQueueFree(CircularQueue* obj);
//销毁循环队列

循环队列初始化

CircularQueue* CircularQueueCreate(int k) 
{
	CircularQueue* cq = (CircularQueue*)malloc(sizeof(CircularQueue));
	cq->queue = (DataType*)malloc((k + 1) * sizeof(DataType));
	cq->front = 0;
	cq->rear = 0;
	cq->length = k + 1;
	return cq;
}

初始化时多开一个空间,防止溢出。

入队列

bool CircularQueueEnQueue(CircularQueue* obj, DataType value) 
{
	if ((obj->rear + 1) % obj->length == obj->front)
		return false;
	obj->queue[obj->rear++] = value;
	if (obj->rear == obj->length)
		obj->rear = 0;

	return true;
}

我们首先要判断队列是否已满,如果满了则返回false,为什么使用这个公式我会在下面的判断队满的函数中写到,没满则将数据存到队尾指针的位置,如果队尾指针达到了我们多开的那个位置,则让队尾指针归零

出队列

bool myCircularQueueDeQueue(CircularQueue* obj) 
{
	if (obj->front == obj->rear)
		return false;;

	++obj->front;
	if (obj->front == obj->length)
		obj->front = 0;
	return true;
}

首先判断是否队空,然后使队头指针走一步,当队头指针到达多开的空间时,归零

获取队首元素

DataType CircularQueueFront(CircularQueue* obj) 
{
	if (obj->front == obj->rear)
		return -1;
	else
		return obj->queue[obj->front];
}

获取队尾元素

DataType CircularQueueRear(CircularQueue* obj) 
{
	if (obj->front == obj->rear)
		return -1;
	else if (obj->rear == 0)
		return obj->queue[obj->length - 1];
	else
		return obj->queue[obj->rear - 1];
}

获取队列中有效元素个数

int CircularQueueSize(CircularQueue* obj)
{
	return (obj->rear - obj -> front + obj->length) % obj->length;
}

首先用队尾位置减去队首位置,然后因为是循环队列,位置不断变化可能会出现负数和得不到正确的结果,我们就需要先加上总长度在对总长度取模,这样得到的才是他们真正的位置差,也就是有效元素个数

检测循环队列是否为空

bool CircularQueueIsEmpty(CircularQueue* obj) 
{
	if (obj->rear == obj->front)
		return true;
	else
		return false;
}

当队首和队尾处于同一位置时说明循环队列为空,因为此时他们的相对位置为零

检测循环队列是否已满

bool CircularQueueIsFull(CircularQueue* obj) 
{
	if ((obj->rear + 1) % obj->length == obj->front)
		return true;
	else
		return false;
}

当队满的时候队首应该在队尾的下一个位置,但因为循环队列位置不断变化,可能出现超过总长度或者归零的情况,所以我们需要对总长度取模来获取他们的相对位置

销毁循环队列

void CircularQueueFree(CircularQueue* obj) 
{
	free(obj->queue);
	obj->queue = NULL;
	free(obj);
	obj = NULL;
}

完整代码
头文件

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef int DataType;
typedef struct {
	DataType* queue;
	int front;
	int rear;
	int length;
} CircularQueue;

CircularQueue* CircularQueueCreate(int k);
//循环队列初始化
bool CircularQueueEnQueue(CircularQueue* obj, DataType value);
//循环队列入队
bool myCircularQueueDeQueue(CircularQueue* obj);
//循环队列出队
DataType CircularQueueFront(CircularQueue* obj);
//获取循环队列队首
DataType CircularQueueRear(CircularQueue* obj);
//获取循环队列队尾
bool CircularQueueIsEmpty(CircularQueue* obj);
//判断循环队列是否为空
bool CircularQueueIsFull(CircularQueue* obj);
//判断循环队列是否已满
void CircularQueueFree(CircularQueue* obj);
//销毁循环队列

函数实现

#pragma once
#include "CircularQueue.h"

CircularQueue* CircularQueueCreate(int k) 
{

	CircularQueue* cq = (CircularQueue*)malloc(sizeof(CircularQueue));
	cq->queue = (DataType*)malloc((k + 1) * sizeof(DataType));
	cq->front = 0;
	cq->rear = 0;
	cq->length = k + 1;
	return cq;
}

bool CircularQueueEnQueue(CircularQueue* obj, DataType value) 
{
	if ((obj->rear + 1) % obj->length == obj->front)
		return false;
	obj->queue[obj->rear++] = value;
	if (obj->rear == obj->length)
		obj->rear = 0;

	return true;
}

bool myCircularQueueDeQueue(CircularQueue* obj) 
{
	if (obj->front == obj->rear)
		return false;;

	++obj->front;
	if (obj->front == obj->length)
		obj->front = 0;
	return true;
}

DataType CircularQueueFront(CircularQueue* obj) 
{
	if (obj->front == obj->rear)
		return -1;
	else
		return obj->queue[obj->front];
}

DataType CircularQueueRear(CircularQueue* obj) 
{
	if (obj->front == obj->rear)
		return -1;
	else if (obj->rear == 0)
		return obj->queue[obj->length - 1];
	else
		return obj->queue[obj->rear - 1];
}

bool CircularQueueIsEmpty(CircularQueue* obj) 
{
	if (obj->rear == obj->front)
		return true;
	else
		return false;
}

bool CircularQueueIsFull(CircularQueue* obj) 
{
	if ((obj->rear + 1) % obj->length == obj->front)
		return true;
	else
		return false;
}

void CircularQueueFree(CircularQueue* obj) 
{
	free(obj->queue);
	obj->queue = NULL;
	free(obj);
	obj = NULL;
}
发布了60 篇原创文章 · 获赞 78 · 访问量 6322

猜你喜欢

转载自blog.csdn.net/qq_35423154/article/details/104481106