循环队列
Posted 四季帆
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了循环队列相关的知识,希望对你有一定的参考价值。
1. 循环队列的概念
在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进:无论插入或删除,一旦rear指针增1或front指针增1 时超出了所分配的队列空间,就让它指向这片连续空间的起始位置,自动从MaxSize-1增1变到0,可用取余运算rear%MaxSize和front%MaxSize来实现。这实际上是把队列空间想象成一个环形空间,环形空间中的存储单元循环使用,用这种方法管理的队列也就称为循环队列。
循环队列就是将队列存储空间的最后一个位置转而绕到第一个位置,形成逻辑上的环状空间,但我们需要注意,实际上循环队列不是一个真正的环,它依旧是单线性的。
使用循环队列虽然可以解决顺序队列中浪费内存的问题,但这里任然存在一个问题,就是对于循环队列而言,队空和队满的条件都是rear==front,导致两种情况无法区分。 为了区分队空和队满,可以采用空一个元素不使用的方法,此时队空的条件为:front==rear,而队满的条件则为:(rear+1)%MAXSIZE == front,从而加以区分。
2. 代码实现
在数组实现的顺序链表基础上进行改进
#include<stdio.h>
#include<stdlib.h>
typedef struct Qnode
{
int *Data;
int Front,Rear;
int Max;
} *Queue;
//创建一个空队列
Queue CreateQueue(int max)
{
Queue q = (Queue)malloc(sizeof(struct Qnode));
q->Data = (int *)malloc(sizeof(int) * max);
q->Front = q->Rear=0;
q->Max = max;
return q;
}
//入队
void AddQueue(Queue q, int data)
{
if ((q->Rear+1)%q->Max == q->Front)
{
printf("ERROR: Queue is full!\\n");
}
else
{
//只能填充MAX-1个数据,永远有一个格子没有数据
q->Rear = (q->Rear+1)%q->Max;
q->Data[q->Rear] = data;
printf("add queue data = %d\\n", data);
}
}
//出队
void OutQueue(Queue q, int *data)
{
if(q->Front == q->Rear)
{
printf("ERROR: Queue is empty\\n");
}
else
{
q->Front = (q->Front+1)%q->Max;
*data = q->Data[q->Front];
}
}
int main()
{
int i, temp;
Queue q;
q=CreateQueue(10); //创建一个队长为10的空队列
//for(i=0;i<10;i++) //入队10个数字是不可以的,入队第10个数字时会报错队列已满
for(i=0;i<9;i++) //一次最多只能入队9个数字,因为环形队列有一个格子是要空着的
AddQueue(q,i);
for(i=0;i<5;i++) //出队5个数字并打印
{
OutQueue(q, &temp);
printf("%d\\n", temp);
}
return 0;
}
3. 总结
数组实现的顺序链表因为空间不能重复使用,实际工作中基本没啥用处,直接PASS;
链表实现的顺序链表空间是可以重复使用的,但是每次入队和出队动作都需要动态申请内存,这对于频繁进行入队和出队的程序来说,是非常影响其效率的;
循环链表是在数组实现的顺序链表上做了些许改进而得到的,它的空间可以重复使用,入队和出队也不需要动态申请内存,所以这种方式在实际工作当中使用得最广泛。
以上是关于循环队列的主要内容,如果未能解决你的问题,请参考以下文章