详解循环队列

定义

循环队列是一种数据结构,它可以在有限的存储空间内实现队列的操作。循环队列通常用数组实现,并且有一个固定的大小。它有两个指针,一个是头指针(front),另一个是尾指针(rear)。在循环队列中,当尾指针到达数组的末端,如果队列仍未满,它会从数组的开始位置继续。

循环队列中的元素可以按照先进先出(FIFO)的顺序进行操作。具体来说,插入元素的操作(通常称为入队)发生在rear指针指向的位置,而删除元素的操作(通常称为出队)发生在front指针指向的位置。当rear指针追上front指针时,队列为空;当front指针追上rear指针时,队列为满。

特点 

  1. 循环队列是一种使用一维数组存储的队列,它通过取模运算实现了队列的环形结构。
  2. 循环队列中,队头指针和队尾指针都是固定位置的,队头指针指向队首元素,队尾指针指向队尾元素的下一个位置。
  3. 循环队列中,当队尾指针到达数组的末端时,如果队列仍未满,它会从数组的开始位置继续。
  4. 循环队列中,先进入的元素先出队,后进入的元素后出队,遵循先进先出原则。
  5. 循环队列在内存中可以高效地利用存储空间,因为它不需要像普通队列那样在删除元素时移动大量元素。
  6. 循环队列需要预先分配一定的存储空间,如果队列未满,则会造成空间的浪费。
  7. 循环队列在进行插入和删除操作时,具有很高的效率,时间复杂度为O(1)。

总之,循环队列是一种高效、实用的数据结构,适用于需要频繁进行插入和删除操作的情况。

基本操作

  1. 初始化:创建一个空的循环队列,并设置相应的头结点和尾结点。
  2. 入队操作:将一个元素添加到循环队列的尾部,需要更新尾结点的指针域和队列的长度属性。
  3. 出队操作:从循环队列的头部删除一个元素,需要更新头结点的指针域和队列的长度属性。
  4. 获取队头元素:获取循环队列的头部元素,需要返回头结点所指向的元素的值。
  5. 判断队列是否为空:检查循环队列是否为空,需要判断头结点和尾结点是否相等。
  6. 判断队列是否已满:检查循环队列是否已满,需要判断队列的长度是否等于其最大容量。
  7. 清空队列:删除循环队列中的所有元素,需要将头结点和尾结点指向同一个位置。

需要注意的是,在循环队列中,头结点和尾结点是相连的,当尾结点到达数组的末端时,如果队列仍未满,它会从数组的开始位置继续。因此,循环队列的入队和出队操作都是在头结点和尾结点之间进行的。

代码实现

1.定义接口


#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);
 
// 输出队列内容  
void printQueue(CirclesQueue *Q);
 
// 获取队列长度  
int getLength(CirclesQueue *Q);
 
// 获取队首元素
DataType getFront(CirclesQueue* Q);

2.初始化


int init(CirclesQueue *Q)
{
	Q->front = Q->rear = 0;
	return 0;
}

3.入队

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;

}

4.队满


int isfull(CirclesQueue *Q)
{
	return (Q->rear+1)%MAXSIZE == Q->front ? 1 : 0;
}

5.出队


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;

}

6.队空

int isempty(CirclesQueue *Q)
{
	return (Q->front == Q->rear) ? 1 : 0;
}

7.输出队列内容

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);

}

8.获取队列长度

int getLength(CirclesQueue *Q) {  
    return (Q->rear - Q->front + MAXSIZE) % MAXSIZE; // 循环队列:若rear在前方,则长度为rear-front+MAXSIZE,否则为rear-front  
}

9.获取队首元素


DataType getFront(CirclesQueue* Q) {  
    int i;
    i = (Q -> front) %MAXSIZE;
    return Q -> data[(i + 1 % MAXSIZE)];
}

完整代码

main.c

#include <stdio.h>
#include "CirclesQueue.h"
#include <string.h>
#include <stdlib.h>
 
int main(int argc, char* argv[])
{
	CirclesQueue Q;
	DataType x;
	int cmd;
	char yn;
int result;
    char welcome[] = "欢迎使用";
	int i = 0; 
	int m = 0; 
	int n = 0;
    for(i=0;i<strlen(welcome);i++)
	{
		printf("%c",welcome[i]);
		for(m=0;m<10000;m++)
			for(n=0;n<1000;n++)
			{
				;
			}
	}
	printf("\n\n\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~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)?");
			getchar();
			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", getFront(&Q));  
            break;
		case 8:
			printf("输出队列:");
			printQueue(&Q);
			printf("\n");
			break;
		case 9:
		    printf("本程序由叶永豪设计开发\n");
		    break;
		}
 
	}while(cmd!=0);
 
 
	return 0;
}

 CirclesQueue.c


#include <stdio.h>
#include "CirclesQueue.h"
 
/*循环队列初始化*/
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;
}
 
// 输出队列内容  
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);
}
 
// 获取队列长度  
int getLength(CirclesQueue *Q) {  
    return (Q->rear - Q->front + MAXSIZE) % MAXSIZE; // 循环队列:若rear在前方,则长度为rear-front+MAXSIZE,否则为rear-front  
} 
 
// 获取队首元素  
DataType getFront(CirclesQueue* Q) {  
    int i;
    i = (Q -> front) %MAXSIZE;
    return Q -> data[(i + 1 % MAXSIZE)];
}
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);
 
// 输出队列内容  
void printQueue(CirclesQueue *Q);
 
// 获取队列长度  
int getLength(CirclesQueue *Q);
 
// 获取队首元素
DataType getFront(CirclesQueue* Q);

运行截图

小结

循环队列是一种特殊的线性表,只允许在表的前端进行删除操作,而在表的后端进行插入操作,且两端都是直接相邻的。循环队列的底层实现一般是用数组来实现的,是采用循环的方式来遍历整个队列。循环队列通过入队和出队操作,可以实现队列的先进先出原则。同时,循环队列在内存中可以高效地利用存储空间,因为它不需要像普通队列那样在删除元素时移动大量元素。但是,循环队列需要预先分配一定的存储空间,如果队列未满,则会造成空间的浪费。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值