一:循环队列的定义
循环队列是一种基于数组实现的队列数据结构,它的特点是队列的尾部指针可以循环到数组的头部,形成一个环形结构。循环队列的定义包括以下几个要素:
-
一个固定大小的数组:循环队列使用一个数组来存储元素,数组的大小是预先指定的。
-
一个头指针(front):指向队列的第一个元素。
-
一个尾指针(rear):指向队列最后一个元素的下一个位置。当队列为空时,头指针和尾指针指向同一个位置。
-
队列长度(size):表示队列中元素的个数。
二:循环队列的运算
循环队列的操作包括入队(enqueue)、出队(dequeue)、判空(isEmpty)、判满(isFull)等。入队操作将元素添加到队列的尾部,出队操作将队列的头部元素移除。由于循环队列的尾指针可以循环到数组的头部,因此入队操作可能会导致尾指针超过数组的边界,此时需要将尾指针循环到数组的开头。同样,出队操作可能会导致头指针超过数组的边界,也需要将头指针循环到数组的开头。
三:循环队列的实现
1.初始化
/*循环队列初始化*/
int init(CirclesQueue *Q)
{
Q->front =0;
Q->rear = 0;
return 0;
}
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;
}
3:队满
/*队满?*/
int isfull(CirclesQueue *Q)
{
return (Q->rear+1)%MAXSIZE == Q->front ? 1 : 0;
}
4.出队
/*出队*/
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;
}
5:对空
/*队空*/
int isempty(CirclesQueue *Q)
{
return (Q->front == Q->rear) ? 1 : 0;
}
6:队列长度
/*队列长度*/
int querylen(CirclesQueue *Q){
return (Q->rear - Q->front + MAXSIZE) % MAXSIZE;
}
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;
}
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");
}
四:Demo
1:main.c
#include <stdio.h>
#include "CirclesQueue.c"
#include "welcome.h"
int main(int argc, char *argv[])
{
CirclesQueue Q;
DataType x, a, len;
int cmd,i, m, n;
char yn;
for (i = 0; i < strlen(welcome); i++)
{
printf("%c", welcome[i]);
for (m = 0; m < 2000; m++)
for (n = 0; n < 2000; 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;
}
2:CirclesQueue.c
/*
CirclesQueue.c
*/
#include <stdio.h>
#include "CirclesQueue.h"
/*循环队列初始化*/
int init(CirclesQueue *Q)
{
Q->front =0;
Q->rear = 0;
return 0;
}
/*入队*/
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;
}
/*队满?*/
int isfull(CirclesQueue *Q)
{
return (Q->rear+1)%MAXSIZE == Q->front ? 1 : 0;
}
/*出队*/
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;
}
/*队空*/
int isempty(CirclesQueue *Q)
{
return (Q->front == Q->rear) ? 1 : 0;
}
/*队列长度*/
int querylen(CirclesQueue *Q){
return (Q->rear - Q->front + MAXSIZE) % MAXSIZE;
}
/*打印队首元素*/
int printfront(CirclesQueue *Q){
DataType a;
if(isempty(Q))
{
printf("队列为空!100002\n");
return 100002;
}else
{
return Q->data[Q->front +1 %MAXSIZE];
}
return 0;
}
/*输出队列*/
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");
}
3:CirclesQueue.h
/*
CirclesQueue.h
循环队列
*/
#include <stdio.h>
#define MAXSIZE 100
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);
4:运行截图
五:小结
循环队列的特点包括:
- 使用数组来存储数据,通过两个指针front和rear来标识队列的头部和尾部。
- 当队列为空时,front和rear指向同一个位置;当队列满时,front和rear指向相邻位置。
- 入队操作是将元素添加到rear指向的位置,并将rear向后移动一位;出队操作是将front向后移动一位,并返回front指向的元素。
循环队列的优点包括:
- 充分利用数组空间,避免了线性队列的数据迁移操作。
- 入队和出队操作的时间复杂度都是O(1),效率较高。
循环队列的缺点包括:
- 队列的容量是固定的,无法动态扩容。
- 队列中的元素个数最多为队列容量减1,因为需要一个位置来区分队列是空还是满。
在实际应用中,循环队列常用于需要频繁进行入队和出队操作的场景,例如操作系统中的进程调度、缓冲区管理等。