环形队列的定义和特点
定义
环形队列是一种特殊的队列数据结构,它可以通过循环利用数组中的空间来实现队列的操作。与普通的队列不同,环形队列的队尾指针可以超过数组的末尾,指向数组的开头,形成一个环状结构。
环形队列的定义包括以下几个要素:
- 一个固定大小的数组,用于存储队列中的元素。
- 一个队头指针,指向队列中的第一个元素。
- 一个队尾指针,指向队列中最后一个元素的下一个位置。
队列为空时,队头指针和队尾指针相等。当向队列中添加元素时,队尾指针向后移动,并将元素放入队尾指针指向的位置。当从队列中删除元素时,队头指针向后移动,并返回队头指针指向的元素。
环形队列的优点是可以充分利用数组的空间,避免了普通队列在队尾指针到达数组末尾后无法再添加元素的问题。同时,环形队列的操作时间复杂度也与普通队列一样,都是O。
特点
环形队列的特点包括:
1. 循环利用空间:环形队列可以通过循环利用数组中的空间来实现队列的操作,避免了普通队列在队尾指针到达数组末尾后无法再添加元素的问题。
2. 固定大小:环形队列的大小是固定的,一旦初始化后,无法动态调整大小。这是因为环形队列使用数组来存储元素,数组的大小是固定的。
3. 队头指针和队尾指针:环形队列有两个指针,一个是队头指针,指向队列中的第一个元素;另一个是队尾指针,指向队列中最后一个元素的下一个位置。队头指针和队尾指针可以超过数组的末尾,形成一个环状结构。
4. 队列满和队列空的判断:当队列满时,队尾指针的下一个位置就是队头指针,即队尾指针+1等于队头指针;当队列空时,队头指针和队尾指针相等。
5. 操作的时间复杂度:环形队列的操作时间复杂度与普通队列一样,都是O(1)。无论是入队、出队还是获取队头元素,都可以在常数时间内完成。
总的来说,环形队列通过循环利用数组的空间,解决了普通队列在队尾指针到达数组末尾后无法再添加元素的问题,同时具有固定大小和常数时间复杂度的特点。
环形队列的基本运算
环形队列的基本运算包括以下几个操作:
-
初始化:创建一个固定大小的数组,并初始化队头指针和队尾指针为0。
-
入队(enqueue):将元素添加到队列的队尾。如果队列已满(队尾指针的下一个位置等于队头指针),则无法入队。否则,将元素放入队尾指针指向的位置,并将队尾指针后移一位。
-
出队(dequeue):从队列的队头删除一个元素,并返回该元素的值。如果队列为空(队头指针和队尾指针相等),则无法出队。否则,将队头指针后移一位,并返回队头指针指向的元素。
-
获取队头元素(front):返回队列的队头元素的值,但不删除该元素。如果队列为空,则返回一个特定的空值。
-
判断队列是否为空(isEmpty):检查队列是否为空,即队头指针和队尾指针是否相等。
-
判断队列是否已满(isFull):检查队列是否已满,即队尾指针的下一个位置是否等于队头指针。
这些基本运算可以满足环形队列的基本需求,通过操作队头指针和队尾指针来实现元素的入队、出队和访问。
环形队列的实现
环形队列的接口定义
#define MAXSIZE 100
typedef int DataType;
typedef struct
{
DataType data[MAXSIZE];
int front;
int rear;
}CirclesQueue;
初始化环形队列
/*循环队列初始化*/
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");
}
运行截图
完整Demo
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;
char yn;
int i,m,n;
for(i=0;i<strlen(welcome);i++)
{
printf("%c",welcome[i]);
for(m=0;m<1000;m++)
for(n=0;n<1000;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;
}
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");
}
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);
welcome.h
char welcome[] = "\n\
............\n\
................\n\
..................\n\
....................\n\
....................\n\
..................\n\
....\ ............../\n\
........... .........................\n\
..............\ /......../######\....../###\.\n\
................v.........##########\...#######\n\
..........................|######/..\##.|####/.\#| ....\n\
..................#####\.,|######....##.|####...#| .......\n\
................|########.|######....##.|####...#| .......\n\
...............#########_|######\../##.|####\./#| /##\....\n\
..............###############################nn\/#######^\n\
\........./ \########~##############nnnnn.###########/\n\
########|##########nnnnn.##############/\n\
#######| \###########################/\n\
\###.##\ \######################\n\
\##.##\ ___ \#############/\n\
\.##\/.../..\ /##/\n\
\##\/..../ /####/\n\
\#############/\n\
Welcome to the mouse program\n\n\n\n";
环形队列的总结
-
环形队列是一种使用数组实现的队列数据结构,通过循环利用数组空间来解决普通队列在队尾指针到达数组末尾后无法再添加元素的问题。
-
环形队列有固定大小,一旦初始化后,无法动态调整大小。
-
环形队列包括队头指针和队尾指针,队头指针指向队列中的第一个元素,队尾指针指向队列中最后一个元素的下一个位置。
-
队列满和队列空的判断:当队列满时,队尾指针的下一个位置就是队头指针;当队列空时,队头指针和队尾指针相等。
-
环形队列的基本运算包括初始化、入队、出队、获取队头元素、判断队列是否为空和判断队列是否已满。
-
环形队列的操作时间复杂度与普通队列一样,都是O(1)。
-
环形队列的优点是可以充分利用数组的空间,避免了普通队列在队尾指针到达数组末尾后无法再添加元素的问题。
-
环形队列的缺点是固定大小,无法动态调整大小。
总的来说,学习环形队列需要了解其原理、特点和基本运算,掌握如何使用数组和指针来实现环形队列的操作。通过理解和练习,可以灵活运用环形队列解决相关问题。