数据结构之循环队列

本文详细介绍了循环队列的数据结构,包括定义、关键指针操作、特殊情况处理、优点(空间效率、连续性)、缺点(复杂性、时间开销),并提供了相关代码实例。
摘要由CSDN通过智能技术生成

一、循环队列

1.定义

循环队列(Circular Queue)是一种使用静态数组实现的队列,它允许在队列的头部和尾部进行插入和删除操作。循环队列在表现上像是一个固定大小的数组,但实际上它使用一个指针来指示队列的头部和尾部。当尾部指针到达数组的末端时,它会从数组的开始处继续。循环队列有效地利用了数组的空间,避免了普通队列中因为头尾指针不断移动而浪费的空间。

2.两个关键的指针

  • front:指向队列的头部元素。
  • rear:指向队列尾部元素的下一个位置。当元素被添加到队列中时,rear 会向前移动一位。

3.两种特殊情况

  • 当 rear 到达数组的末端时,需要将 rear 重新指向数组的开始。
  • 当 front 到达数组的末端时,需要将 front 重新指向数组的开始。

循环队列可以有效地处理队列满和队列空的情况。在普通队列中,当队列满时,最后一个元素之后将没有空间添加新元素,导致队列溢出。但在循环队列中,当 rear 到达数组的末端时,它将自动回到数组的开始,从而为添加新元素腾出空间。同样,当 front 和 rear 相遇时,意味着队列为空。

你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

4.优点

  • 有效地利用了数组空间,避免了普通队列中因为头尾指针不断移动而浪费的空间。
  • 循环队列通过在尾部添加新元素和头部删除元素的方式,使得队列操作具有连续性,减少了因删除元素导致的大量移动操作。
  • 循环队列可以动态地扩展队列容量,避免了普通队列中因固定容量导致的空间浪费或溢出问题。

5.缺点

  • 需要在实现时额外维护一个记录队列长度的变量,增加了编程的复杂性。
  • 在进行出队操作时,需要比较头尾指针的位置关系,增加了判断操作的时间开销。
  • 在进行入队操作时,需要比较队列长度和队列容量的大小关系,增加了比较操作的时间开销。
  • 在循环队列实现中,如果未处理入队和出队时头尾指针位置相同的特殊情况,会导致错误的判断队列为空或已满的条件。

二、代码及运行

1.初始化

int init(CirclesQueue *Q)
{
	Q->front = 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 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;
}

出队

4.输出队列

void print(CirclesQueue *Q)
{
	int i;
	if(isempty (Q))
	{
		print("队列为空!\n");
		return;
	}
	i=(Q->front)% MAXSIZE;
	do
	{
		printf("%d",Q->data[(i+1)% MAXSIZE]);
		i=(i+1)% MAXSIZE;
	}while(i!=Q->rear);
}

在这里插入图片描述

5.取队头元素

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

取队头元素

6.队列长度

int length(CirclesQueue *Q)
{
return Q->rear-Q->front +MAXSIZE%MAXSIZE;
}

队列长度

7.队满?

if(isfull(&Q))
			{
	    	printf("队列已满!100001\n");
			}else
				printf("队列未满");

队满?

8.队空?

if(isempty(&Q))
			{
	    	printf("队列为空!100002\n");
			}else
				printf("队列不为空");

队空?

9.帮助

printf("感谢季老师对我的关心和支持,让我在学习过程中充满信心和动力");

帮助

三、整体代码

  • main.c
#include <stdio.h>
#include "CirclesQueue.h"


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:
			print(&Q,&x);
			break;
		case 5:
			printf("%d",printw(&Q));
			break;
		case 6:
         	printf("%d",length(&Q));
			break;
		case 7:
			if(isfull(&Q))
			{
	    	printf("队列已满!100001\n");
			}else
				printf("队列未满");
			
			break;
		case 8:
			if(isempty(&Q))
			{
	    	printf("队列为空!100002\n");
			}else
				printf("队列不为空");
			break;
		case 9:
			printf("感谢季老师对我的关心和支持,让我在学习过程中充满信心和动力");
			break;
		}

	}while(cmd!=0);


	return 0;
}
  • CirclesQueue.c
#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 print(CirclesQueue *Q)
{
	int i;
	if(isempty (Q))
	{
		print("队列为空!\n");
		return;
	}
	i=(Q->front)% MAXSIZE;
	do
	{
		printf("%d",Q->data[(i+1)% MAXSIZE]);
		i=(i+1)% MAXSIZE;
	}while(i!=Q->rear);
}

/*取队头*/
int printw(CirclesQueue *Q )
{
 return Q->data[Q->front +1 %MAXSIZE];
}
/*队列长度*/
int length(CirclesQueue *Q)
{
return Q->rear-Q->front +MAXSIZE%MAXSIZE;
}
  • 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;
}

/*输出队列*/
void print(CirclesQueue *Q)
{
	int i;
	if(isempty (Q))
	{
		print("队列为空!\n");
		return;
	}
	i=(Q->front)% MAXSIZE;
	do
	{
		printf("%d",Q->data[(i+1)% MAXSIZE]);
		i=(i+1)% MAXSIZE;
	}while(i!=Q->rear);
}

/*取队头*/
int printw(CirclesQueue *Q )
{
 return Q->data[Q->front +1 %MAXSIZE];
}
/*队列长度*/
int length(CirclesQueue *Q)
{
return Q->rear-Q->front +MAXSIZE%MAXSIZE;
}

四、小结

循环队列是数据结构中一个非常经典的概念,相对于其他队列结构,循环队列可以优化存储空间的使用,减少空间的浪费。循环队列的操作也比较高效,能够快速执行入队和出队操作。经过这次的作业,我对循环队列结构进行了深入的了解与实践,更深刻地认识到了数据结构的重要性。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值