本文最后更新于565 天前,其中的信息可能已经过时,如有错误请发送邮件到1986413837@qq.com

这是一个size为7的循环队列示意图

方式一 顺序循环结构
为了辨别 队列为空 和 队列为满的两种情况 只在size-1的存储单元里存储数据 若不这样设计 这两者的判断条件都是Q.front=Q.rear 这是不方便的
重点!!! 构建循环下标
使用循环计算((index + 1) % size),可以有效避免索引越界的问题。当 index 达到 size - 1 时,使用取模运算会自动回到 0,从而实现循环效果

- 即使
rear是 0,rear - 1也不会导致负数 通过将obj->size加到rear - 1,确保了索引在进行取模计算时不会出现负数 - 这个取模操作用于实现循环效果,确保在数组索引的范围内。如果
rear减 1 的结果为负数,通过取模运算会得到数组的有效索引
搞懂了这两个循环就可以开始构建循环队列了 下面是源代码实现
//构建队列结构体
typedef struct {
int front;
int rear;
int size;
int* elements;
} MyCircularQueue;
//判断是否为空
bool IsEmpty(MyCircularQueue* obj) {
return obj->front == obj->rear;
}
//判断是否满队列
bool IsFull(MyCircularQueue* obj) {
return (obj->rear + 1) % obj->size == obj->front;
}
//初始化循环队列 注意!!! 令Size为 k+1
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* queue = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
queue->front = queue->rear = 0;
queue->size = k + 1;
queue->elements = (int*)malloc(queue->size * sizeof(int));
return queue;
}
//rear在队尾元素的下一个位置!
//入队列先判断是否为满队列 在队列尾部添加 rear移动到下一个位置
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if (IsFull(obj))return false;
obj->elements[obj->rear] = value;
//循环索引更新
//0--size-1
obj->rear = (obj->rear + 1) % obj->size;
return true;
}
//出队列先判断是否为空队列 在队列头部删除 直接移动队首元素即可
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if (IsEmpty(obj))return false;
//循环索引更新
//0--size-1
obj->front= (obj->front + 1) % obj->size;
return true;
}
int myCircularQueueFront(MyCircularQueue* obj) {
if (IsEmpty(obj))return -1;
return obj->elements[obj->front];
}
//rear在队尾元素的下一个位置!
int myCircularQueueRear(MyCircularQueue* obj) {
if (IsEmpty(obj))return -1;
//队尾元素在rear的前一个位置
//这里要防止rear下标为0的情况
//0--size-1
return obj->elements[(obj->rear - 1 + obj->size) % obj->size];
}
//清空队列
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->elements);
free(obj);
}
方式二 链队列结构
这种方式比较简单 给队列一个size表示当前队列大小 一个capacity表示队列容量
代码实现如下 比较简单
typedef struct Node
{
Node* next;
int data;
}Node;
typedef struct Queue{
Node* front;
Node* rear;
int size;
int capacity;
}Queue;
bool ifEmpty(Queue*queue)
{
return queue->size == 0;
}
bool ifFull(Queue* queue)
{
return queue->size == queue->capacity;
}
void initQueue(Queue* queue,int k)
{
queue->rear = queue->front = (Node*)malloc(sizeof(Node));
queue->rear = queue->front = NULL;
queue->size = 0;
queue->capacity = k;
}
void EnQueue(Queue* queue, int val)
{
if (ifFull(queue))return;
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = val;
if (ifEmpty(queue))
{
queue->rear = queue->front = newNode;
}
else
{
queue->rear->next = newNode;
queue->rear = newNode;
}
queue->size++;
}
void DeQueue(Queue* queue)
{
if (ifEmpty(queue))return;
Node* curr = queue->front;
queue->front = curr->next;
queue->size--;
free(curr);
}
int Front(Queue* queue) {
if (queue->size == 0) {
return -1;
}
return queue->front->data;
}
int Rear(Queue* queue) {
if (queue->size == 0) {
return -1;
}
return queue->rear->data;
}
void FreeQueue(Queue* queue)
{
Node* curr = queue->front;
while (curr)
{
Node* temp = curr;
curr = curr->next;
free(temp);
}
free(queue);
}
void printQueue(Queue* queue)
{
Node* curr = queue->front;
while (curr)
{
printf("%d ", curr->data);
curr = curr->next;
}
}