一、环形队列的概念
循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。
定义
环形队列也是队列的一种数据结构, 也是在队头出队, 队尾入队;
只是环形队列的大小是确定的, 不能进行一个长度的增加, 当你把一个环形队列创建好之后, 它能存放的元素个数是确定的;
一般我们实现这个环形队列是通过一个连续的结构来实现的;
虽然环形队列在逻辑上是环形的, 但在物理上是一个定长的数组;
环形队列可以用于很多场景,比如计算机中的任务调度、打印机任务队列等等
优缺点
优点:可以循环利用存储空间,节省存储空间,可以快速地在队列头和队列尾进行操作,具有固定大小的存储空间,可以避免内存泄漏等问题。
缺点:需要额外的指针来维护队列的状态,增加了复杂度,队列的大小必须预先定义好,难以动态调整。
二、代码实现
1、接口定义
/*
CirclesQueue.h
循环队列
*/
#include <stdio.h>
#define MAXSIZE 5
typedef int DataType;
typedef struct
{
DataType data[MAXSIZE];
int front;
int rear;
}CirclesQueue;
/*循环队列初始化*/
int init(CirclesQueue *Q);
/*入队*/
int enqueue(CirclesQueue *Q, DataType x);
/*队满?*/
int isfull(CirclesQueue *Q);
/*出队*/
int dequeue(CirclesQueue *Q, DataType *);
/*队空*/
int isempty(CirclesQueue *Q);
/*队长*/
int querylen(CirclesQueue *Q);
/*打印队首元素*/
int printfront(CirclesQueue *Q);
/*输出队列*/
void querylist(CirclesQueue *Q);
2、接口实现
2.1 循环队列初始化
/*循环队列初始化*/
int init(CirclesQueue *Q)
{
Q->front =0;
Q->rear = 0;
return 0;
}
2.2 入队操作
/*入队*/
int enqueue(CirclesQueue *Q, DataType x)
{
if(isfull(Q))
{
printf("队列已满!100001\n");
return 100001;
}
Q->rear = (Q->rear+1) % MAXSIZE;
Q->data[Q->rear] =x;
return 0;
}
2.3 出队操作
/*出队*/
int dequeue(CirclesQueue *Q, DataType *x)
{
if(isempty(Q))
{
printf("队列为空!100002\n");
return 100002;
}
Q->front = (Q->front+1) % MAXSIZE;
*x = Q->data[Q->front];
return 0;
}
2.4 队列是否为空
/*队空*/
int isempty(CirclesQueue *Q)
{
return (Q->front == Q->rear) ? 1 : 0;
}
2.5 队列是否已满
/*队满*/
int isfull(CirclesQueue *Q)
{
return (Q->rear+1)%MAXSIZE == Q->front ? 1 : 0;
}
2.6 队列长度
/*队列长度*/
int querylen(CirclesQueue *Q){
return (Q->rear - Q->front + MAXSIZE) % MAXSIZE;
}
2.7 打印队首元素
/*打印队首元素*/
int printfront(CirclesQueue *Q){
DataType a;
if(isempty(Q))
{
printf("队列为空!100002\n");
return 100002;
}else
{
return Q->data[Q->front +1 %MAXSIZE];
}
return 0;
}
2.8 输出队列
/*输出队列*/
void querylist(CirclesQueue *Q)
{
int i;
if (isempty(Q))
{
/* code */
printf("队列为空\n");
return;
}
i = (Q->front)%MAXSIZE;
printf("队列:");
do
{
printf("%d",Q->data[i + 1 % MAXSIZE]);
i = (i + 1) % MAXSIZE;
} while (i != Q->rear);
printf("\n");
}
2.9 main方法
#include <stdio.h>
#include "CirclesQueue.h"
char welcome[] = "\n// _ooOoo_ //\n// o8888888o //\n// 88”.“88 //\n// (| ^_^ |) //\n// O\ = /O //\n// ____/`---'\____ //\n// .' \\| |// `. //\n// / \\||| : |||// \ //\n// / _||||| -:- |||||- \ //\n// | | \\\ - /// | | //\n// | \_| ''\---/'' | | //\n// \ .-\__ `-` ___/-. / //\n// ___`. .' /--.--\ `. . ___ //\n// .‘’ '< `.___\_<|>_/___.' >' ‘’. //\n// | | : `- \`.;`\ _ /`;.`/ - ` : | | //\n// \ \ `-. \_ __\ /__ _/ .-` / / //\n// ========`-.____`-.___\_____/___.-`____.-'======== //\n// `=---=' //\n// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //\n// 佛祖保佑 永不宕机 永无BUG //\n\n";
int main(int argc, char* argv[])
{
CirclesQueue Q;
DataType x,a,len;
int cmd;
char yn;
for(int i=0;i<strlen(welcome);i++)
{
printf("%c",welcome[i]);
for(int m=0;m<10000;m++)
for(int n=0;n<300;n++)
{
}
}
do
{
printf("-----------循环队列演示-----------\n");
printf(" 1. 初始化\n");
printf(" 2. 入队\n");
printf(" 3. 出队\n");
printf(" 4. 队空\n");
printf(" 5. 队满\n");
printf(" 6. 队列长度\n");
printf(" 7. 打印队首元素\n");
printf(" 8. 打印队列\n");
printf(" 9. 帮助\n");
printf(" 0. 退出\n");
printf(" 请选择(0~8):");
scanf("%d",&cmd);
switch(cmd)
{
case 1:
init(&Q);
printf("队列已初始化!\n");
break;
case 2:
printf("请输入要入队的元素x=");
scanf("%d", &x);
if(!enqueue(&Q,x))
{
printf("元素x=%d已入队\n", x);
}
break;
case 3:
printf("确定要出队(出队会将删除对首元素, y or n, n)?");
fflush(stdin);
scanf("%c", &yn);
if(yn == 'y' || yn == 'Y')
{
if(!dequeue(&Q,&x))
{
printf("队首元素【%d】已出队!\n", x);
}
}
break;
case 4:
if (isempty(&Q) == 1)
{
printf("队列为空!\n");
}else{
printf("队列不是空的!\n");
}
break;
case 5:
if (isfull(&Q) == 1)
{
printf("队列已满!\n");
}else{
printf("队列未满!\n");
}
break;
case 6 :
len = querylen(&Q);
printf("队列长度为【%d】\n",len);
break;
case 7:
a = printfront(&Q);
printf("队首元素为【%d】\n",a);
break;
case 8:
querylist(&Q);
break;
case 9:
printf("本程序为环形队列的演示程序,由杜露设计开发,本程序演示了环形队列功能!\n");
break;
}
}while(cmd!=0);
return 0;
}
3、运行结果
三、小结
环形队列实际开辟的空间大小要比所存数据的队列长度多开辟一个空间的大小。如果环形队列实际开辟的空间大小和所存储数据个数一样时,会导致环形队列所处空的状态和满的状态是一样的。这样便无法区分。因此环形队列必须多留出一个空间,这个空间不能存放数据,这样才能很好的区别环形队列的状态是空还是满。
参考文献
百度百科、CSDN、数据结构(C语言版)