赞
踩
循环队列(Circular Queue),也被称为环形队列或循环缓冲区,是一种队列数据结构,它具有固定大小的缓冲区,允许在队列的前面和后面插入和删除元素。与普通队列不同,循环队列可以避免浪费存储空间的问题,因为当队列的尾部元素达到缓冲区的末尾时,它可以"循环"到缓冲区的开头。
固定大小:循环队列有一个预定义的大小,一旦分配了这个大小,就不能动态调整。
循环性质:当队列的尾部指针(rear)到达缓冲区的末尾时,下一个元素将被插入到缓冲区的开头。这种循环性质使得队列的数据结构紧凑,不会浪费存储空间。
前后指针:循环队列通常有两个指针,一个指向队列的头部(front),另一个指向队列的尾部(rear)。
满队列判定:为了区分队列是空的还是满的,可以采用不同的方法。一种常见的方法是在插入元素时检查(rear+1)%n == front,其中n是队列的大小。如果这个条件成立,队列被认为是满的。
避免数据搬移:与普通队列相比,循环队列的插入和删除操作更加高效,因为元素不需要搬移。普通队列在出队操作后,需要将后续元素向前搬移一个位置,而循环队列不需要这样做。
应用:循环队列常常用于需要固定大小缓冲区的场景。
入队:在队尾插入元素,并将rear指针向后移动。
出队:从队头删除元素,并将front指针向后移动。
判满:检查队列是否已满。
判空:检查队列是否为空。
5.1结构体
- #define MAXSIZE 100
-
- typedef int DataType;
-
- typedef struct
- {
- DataType data[MAXSIZE];
- int front;
- int rear;
- }CirclesQueue;
5.2初始化
接收一个指向循环队列的指针,函数返回0,表示初始化成功。
- /*循环队列初始化*/
- int init(CirclesQueue *Q);
-
- /*循环队列初始化*/
- int init(CirclesQueue *Q)
- {
- Q->front = Q->rear = 0;
- return 0;
- }
运行图:
5.3入队:需要判断队列是否满了,若不满,则可入队
- /*入队*/
- int enqueue(CirclesQueue *Q, DataType x);
- /*入队*/
- 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;
- }
首先检查队列是否已满。如果队列已满,则打印一条消息"队列已满!100001",并返回一个错误代码100001。 如果队列没有满,那么函数会计算rear
指针的新位置。在循环队列中,当rear
指针到达数组的末尾时,它会循环回到数组的开头。函数返回0,表示操作成功。
5.4出队
首先检查队列是否为空。如果队列为空,则打印一条消息"队列为空!100002",并返回一个错误代码100002。
- /*出队*/
- int dequeue(CirclesQueue *Q, DataType *);
- /*出队*/
- 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.5队满
队列的rear
指针加1后对MAXSIZE
取模的结果等于front
指针,那么队列已满,函数返回1;否则,队列未满,函数返回0。
-
- /*队满?*/
- int isfull(CirclesQueue *Q);
-
- /*队满?*/
- int isfull(CirclesQueue *Q)
- {
- return (Q->rear+1)%MAXSIZE == Q->front ? 1 : 0;
- }
5.6队空:队列的front
指针和rear
指针相等,那么队列为空,函数返回1;否则,队列不为空,函数返回0。
-
- /*队空*/
- int isempty(CirclesQueue *Q);
-
- /*队空*/
- int isempty(CirclesQueue *Q)
- {
- return (Q->front == Q->rear) ? 1 : 0;
- }
5.7求队列长度:队列的长度可以通过计算rear
指针和front
指针之间的距离来得到。
- //队列长度
- int getLength(CirclesQueue *Q);
- //队列长度
- int getLength(CirclesQueue *Q) {
- return (Q->rear - Q->front + MAXSIZE) % MAXSIZE;
- }
5.8输出队列:检查队列是否为空。
- // 输出队列内容
- void printQueue(CirclesQueue *Q);
- // 输出队列内容
- void printQueue(CirclesQueue *Q) {
- int i;
- if (isempty(Q)) {
- printf("队列为空.\n");
- return;
- }
- i = (Q -> front) %MAXSIZE;
- do{
- printf(" %d",Q -> data[(i + 1 % MAXSIZE)]);
- i = (i+1) %MAXSIZE;
- }while(i != Q -> rear);
- }
5.9:取队首
- DataType getFront(CirclesQueue* Q);
- // 获取队首元素
- DataType getFront(CirclesQueue* Q) {
- int i;
- i = (Q -> front) %MAXSIZE;
- return Q -> data[(i + 1 % MAXSIZE)];
- }
5.10帮助:
- case 9:
- printf("这个程序由万佳劲编写,有初始化队列,入队,出队,判断为空,是否满,队首,队列长度,输出队列功能,如有问题,请及时联系作者\n");
- break;
6.完整demo
6.1CirclesQueue.h
- /*
- CirclesQueue.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 getLength(CirclesQueue *Q);
- // 输出队列内容
- void printQueue(CirclesQueue *Q);
- // 获取队首元素
- DataType getFront(CirclesQueue* Q);
6.2 CirclesQueue.c
- /*
- CirclesQueue.c
- */
-
- /*循环队列初始化*/
- int init(CirclesQueue *Q)
- {
- Q->front = 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 getLength(CirclesQueue *Q) {
- return (Q->rear - Q->front + MAXSIZE) % MAXSIZE;
- }
-
- // 输出队列内容
- void printQueue(CirclesQueue *Q) {
- int i;
- if (isempty(Q)) {
- printf("Queue is empty.\n");
- return;
- }
- i = (Q -> front) %MAXSIZE;
- do{
- printf(" %d",Q -> data[(i + 1 % MAXSIZE)]);
- i = (i+1) %MAXSIZE;
- }while(i != Q -> rear);
- }
-
- // 获取队首元素
- DataType getFront(CirclesQueue* Q) {
- int i;
- i = (Q -> front) %MAXSIZE;
- return Q -> data[(i + 1 % MAXSIZE)];
- }
welcome
- char welcome[] = "\n\
- \t_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";
main.c
- int main(int argc, char* argv[]) {
- CirclesQueue Q;
- DataType x;
- int cmd;
- char yn;
- 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~6):");
- 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)?");
- // flushall();
- scanf("%c", &yn);
-
- if (yn == 'y' || yn == 'Y') {
- if (!dequeue(&Q, &x)) {
- printf("队首元素【%d】已出队!\n", x);
- }
- }
- break;
- case 4:
- if(isempty(&Q)) printf("队列为空!\n");
- else printf("队列不为空!\n");
- break;
- case 5:
- if(isfull(&Q)) printf("队列已满!\n");
- else printf("队列还没有满!\n");
- break;
- case 6:
- printf("队列的长度:%d\n",getLength(&Q));
- break;
- case 7:
- printf("输出队列:%d\n");
- printQueue(&Q);
- printf("\n");
- break;
- case 8:
- printf("取队首:%d\n",getFront(&Q));
- break;
- case 9:
- printf("这个程序由万佳劲编写,有初始化队列,入队,出队,判断为空,是否满,队首,队列长度,输出队列功能,如有问题,请及时联系作者\n");
- break;
-
- }
-
- } while (cmd != 0);
-
-
- return 0;
- }
7.总结
实现循环队列时,需要小心处理rear和front指针的循环移动,确保在操作时正确地维护它们的位置。
总之,循环队列是一种非常有用的数据结构,适用于需要固定大小缓冲区的情况,可以有效地管理元素的插入和删除,而不浪费存储空间。感谢季老师的教学与指导,才有了最终的一篇拙作。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。