数据结构——循环队列详解

这篇具有很好参考价值的文章主要介绍了数据结构——循环队列详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、循环队列的定义

二、 循环队列的基本操作

三、循环队列的实现 

1、循环队列的定义

2、循环队列的初始化 

3、循环队列出队 

4、循环队列入队 

5、队列判空

6、 队列判满

7、取队头元素

8、输出队列 

9、求队列长度 

四、完整代码 

五、小结 

六、参考文献


一、循环队列的定义

定义:队列主要有顺序队列,循环队列,双端队列,优先队列。而当中循环队列是一种线性数据结构。它也被称为“环形缓冲器”。它只允许在一端进行插入操作,即队尾(rear),而在另一端进行删除操作,即队头 (front),其操作表现基于FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。向队列中插入新的数据元素称为入队,新入队的元素就成为了队列的队尾元素。

特点:

  1. 循环队列允许元素在队尾插入,在队头删除,同时遵循先进先出原则。
  2. 由于循环队列是基于数组实现的,所以它的访问速度很快,特别是在移动元素时。
  3. 如果需要大量添加和删除元素,循环队列比链表更有效率,因为它不需要频繁地移动指针来访问元素。
  4. 不支持随机访问元素,因此不能像数组那样直接访问特定位置的元素。

循环队列,数据结构

二、 循环队列的基本操作

1、初始化:这是创建一个空的顺序队列,需要设定队首指针front和队尾指针rear都指向同一个位置,一般初始都设置为0,即队列为空。

2、元素入队:也被称为插入操作,是将一个新元素添加到队列尾部的操作。

3、元素出队:也被称为删除操作,是将队列头部的元素移除的操作。

4、求队列长度:可以通过计算队尾指针和队首指针之差的值再加1来获取当前队列的长度。

5、判断是否为空:通过检查队首指针front和队尾指针rear是否相等来判断队列是否为空。

6、判断是否为满:当队尾指针指向数组的最后一个位置时,下一个要插入的位置就是队头指针。

7、取队头:头元素就是队列中的第一个元素,可以通过返回队首指针front的值来获取。

8、输出队列:将队列中元素通过while语句循环语句打印出来

三、循环队列的实现 

1、循环队列的定义

用一个数组来存储队列中的元素,用front作为队头指针,指向队列的第一个元素,用rear作为队尾指针,即指向队列最后一个元素的下一个位置.

#define MAXSIZE 4

typedef int DataType;

typedef struct
{
	DataType data[MAXSIZE];
	int front;
	int rear;
}CirclesQueue;

2、循环队列的初始化 

循环队列的初始化只需要将队头指针(front)和队尾指针(rear)都初始化为0.

/*循环队列初始化*/
int init(CirclesQueue *Q)
{
	Q->front = Q->rear = 0;
	return 0;
}

3、循环队列出队 

出队前判断队列是否为空,如果为空,返回100002错误信息,如果队列不为空,将队列的队头指针向前移动一位,即将队头指针加1并对MAXSIZE取模,确保指针在数组范围内循环移动,当到达数组末尾时,会回到数组的开头。

/*出队*/
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、循环队列入队 

入队前需要判断队列是否已经满了,如果队列为满,则不能入队。反之,则将队列的队头向前移动一位,确保指针在数组范围内能够循环移动。具体来说,就是将当前队头指针的值加1,然后对队列的最大容量(MAXSIZE)取模来实现。

/*入队*/
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;
}

5、队列判空

判断循环队列是否为空通过比较队头指针和队尾指针是否相等来判断,如果它们相等,说明队列中没有元素,反之则存在元素。 

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

6、 队列判满

判断循环队列是否为满可以让队列的rear指针加1之后对MAXSIZE取模结果等于front指针,这时表明队列已满,反之则未满。

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

7、取队头元素

想要获取队头元素,首先需要判断队列是否为空,如果为空,返回错误信息。不为空时,可以通过计算front加1后对MAXSIZE取模获取队首元素的位置。

/*取队头元素*/
int QueueFront(CirclesQueue *Q,DataType *x)
{
	if(isempty(Q))
	{
		printf("队列为空!100002\n");
		return 100002;
	}
	*x = Q->data[(Q->front + 1) % MAXSIZE];
	return 0;

8、输出队列 

输出队列前需要先判断队列是否为空,如果为空则输出队列为空,不为空时,将队头指针的值赋给i,并对最大容量MAXSIZE取模,再通过do-while循环来遍历队列中的元素,循环的内部通过计算(i + 1 % MAXSIZE)来获取下一个元素的索引,并输出打印当前元素,同时更新i的值,使其加1并对MAXSIZE取模,以便继续遍历队列。

/*输出队列*/
void PrintQueue(CirclesQueue *Q){
	int i;
	if (isempty(Q))
	{
		printf("队列为空!\n");
		return;
	}
	i=(Q->front)%MAXSIZE;    //确保i的值在0到MAXSIZE-1之间,以便在后续操作中作为数组索引使用
	do
	{
		printf("%d、",Q->data[(i + 1 % MAXSIZE)]);
		i=(i+1)%MAXSIZE;
	}while(i!=Q->rear);
}

9、求队列长度 

求循环队列的长度可以通过计算队列的尾指针(rear)和头指针(front)之间的差值,加上最大容量(MAXSIZE),然后对最大容量取模,得到队列的实际长度。最后,将计算结果存储在指针x所指向的位置,并返回0表示成功。

*获取队列长度*/ 
int getLength(CirclesQueue *Q,DataType *x) {  
  *x= (Q->rear - Q->front + MAXSIZE) % MAXSIZE; 
  return 0;
}

四、完整代码 

1、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:
			if(isempty(&Q))
			{
				printf("队列为空!\n");
			}
			else{
				printf("队列不为空!\n");
			}
			break;
		case 5:
			if(isfull(&Q))
			{
				printf("队列为满!\n");
			}
			else{
				printf("队列未满!\n");
			}
			
			break;
		case 6:
			if(!QueueFront(&Q,&x))
			{
				printf("队首元素为【%d】!\n", x);
			}
			break;
		case 7:
			PrintQueue(&Q);
			printf("\n");
			break;
		case 8:
			if(!getLength(&Q,&x))
			{
				printf("队列长度为【%d】!\n", x);
			}
			break;
		case 9:
			printf("本程序由zzb设计开发,实现了循环队列的入队、出队、取队头等操作\n");

		}

	}while(cmd!=0);


	return 0;
}

2、 CirclesQueue.c

/*
	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;
}
/*取队头元素*/
int QueueFront(CirclesQueue *Q,DataType *x)
{
	if(isempty(Q))
	{
		printf("队列为空!100002\n");
		return 100002;
	}
	*x = Q->data[(Q->front + 1) % MAXSIZE];
	return 0;


}
/*输出队列*/
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);
}
/*获取队列长度*/ 
int getLength(CirclesQueue *Q,DataType *x) {  
  *x= (Q->rear - Q->front + MAXSIZE) % MAXSIZE; 
  return 0;
}


3、 CirclesQueue.h

/*
	CirclesQueue.h
	循环队列
*/

#define MAXSIZE 4

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

/*队空*/
int isempty(CirclesQueue *Q);
/*取队头元素*/
int QueueFront(CirclesQueue *Q,DataType *x);
/*输出队列*/
void PrintQueue(CirclesQueue *Q);
/*队列长度*/
int getLength(CirclesQueue *Q,DataType *x);

4、运行截图 

循环队列,数据结构

五、小结 

1、循环队列是一种线性数据结构。它也被称为“环形缓冲器”。它只允许在一端进行插入操作,即队尾(rear),而在另一端进行删除操作,即队头 (front),其操作表现基于FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。

2、循环队列的应用范围非常广泛,比如线程池任务调度、消息队列系统、缓冲区管理、广度优先搜索算法等应用场景。

3、队列满时,无法再进行插入操作;当队列空时,无法再进行删除操作。队列的大小是固定的,一旦创建后不能改变。

 六、参考文献

 文章来源地址https://www.toymoban.com/news/detail-764948.html

《数据结构》(C语言版)李刚,刘万辉.北京:高等教育出版社 ,2017.   

《C语言程序设计》(第四版)谭浩强. 北京:清华大学出版社,2014.

  CSDN 数据结构-----循环队列

 

 

 

 

 

到了这里,关于数据结构——循环队列详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 数据结构—循环队列(环形队列)

    数据结构—循环队列(环形队列)

    循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且 队尾被连接在队首之后以形成一个循环 。它也被称为“ 环形缓冲器 ”。 循环队列的一个好处是可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素

    2024年02月11日
    浏览(8)
  • 【数据结构和算法】--队列的特殊结构-循环队列

    【数据结构和算法】--队列的特殊结构-循环队列

    循环队列是队列的一种特殊结构,它的 长度是固定的 k ,同样是 先进先出 ,理论结构是 首尾相连的环形循环结构 。其理论结构大致如下: 具体结构描述可以参考 LeetCode : 622. 设计循环队列的题目要求,大致如下: 设计你的循环队列实现。 循环队列是一种 线性数据结构 ,

    2024年02月04日
    浏览(10)
  • 数据结构:循环队列的实现(leetcode622.设计循环队列)

    数据结构:循环队列的实现(leetcode622.设计循环队列)

      目录 一.循环队列简单介绍 二.用静态数组实现循环队列 1.数组循环队列结构设计 2.数组循环队列的堆区内存申请接口  3.数据出队和入队的接口实现 4.其他操作接口 5.数组循环队列的实现代码总览  三.静态单向循环链表实现循环队列  1.链表循环队列的结构设计 2.创建静态

    2024年02月03日
    浏览(9)
  • 数据结构--循环队列、链队

    //循环队列数据结构 typedef struct { QElemType data[MaxQSize];//数据域 int front,rear; //队头队尾指针 }SqQueue; //链队结点数据结构 typedef struct QNode { int data;//数据域 struct QNode* next;//指针域 }QNode, * QueuePtr; typedef struct { struct QNode* front, * rear;//rear指针指向队尾 用于入队 front指针指向队头 用于

    2024年02月15日
    浏览(18)
  • 【数据结构】循环队列

    【数据结构】循环队列

    🚀 作者简介:一名在后端领域学习,并渴望能够学有所成的追梦人。 🐌 个人主页:蜗牛牛啊 🔥 系列专栏:🛹数据结构、🛴C++ 📕 学习格言:博观而约取,厚积而薄发 🌹 欢迎进来的小伙伴,如果小伙伴们在学习的过程中,发现有需要纠正的地方,烦请指正,希望能够与

    2024年02月12日
    浏览(13)
  • 数据结构——循环队列的实现

    数据结构——循环队列的实现

    hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 💥 个人主页:大耳朵土土垚的博客 💥 所属专栏:数据结构学习笔记 💥对于数据结构顺序表、链表、堆有疑问的都可以在上面数据结构的专栏进行学习哦~ 有问题可以写在评论区或者私信

    2024年03月24日
    浏览(9)
  • 九、数据结构——顺序队列中的循环队列

    九、数据结构——顺序队列中的循环队列

    一、循环队列的定义 二、循环队列的实现 三、循环队列的基本操作 ①初始化 ②判空 ③判满 ④入队 ⑤出队 ⑥获取长度 ⑦打印 四、循环队列的应用 五、全部代码 在数据结构中,队列(Queue)是一种常见的线性数据结构,遵循先进先出(First In First Out,FIFO)的原则。循环队

    2024年02月15日
    浏览(14)
  • 数据结构第九弹---循环队列

    数据结构第九弹---循环队列

    顺序队列在使用过程中容易出现虚假的满状态, 为了解决这个问题,就产生了一个较巧妙的方法,将顺序队列臆造为一个环状的空间,称之为循环队列。循环队列中指针和队列元素之间的关系不变,我们只需要利用模运算就可以很容易实现指针的循环移动。但是循环队列中存

    2024年01月16日
    浏览(8)
  • 【数据结构与算法】设计循环队列

    【数据结构与算法】设计循环队列

      🧑‍🎓 个人主页:简 料   🏆 所属专栏:C++   🏆 个人社区:越努力越幸运社区   🏆 简       介: 简料简料,简单有料~在校大学生一枚,专注C/C++/GO的干货分享,立志成为您的好帮手 ~ C/C++学习路线 (点击解锁) ❤️ C语言阶段(已结束) ❤️ 数据结构与算法(ing) ❤

    2024年01月17日
    浏览(12)
  • 数据结构OJ:设计循环队列

    数据结构OJ:设计循环队列

    本题为LeetCode上的经典题目,题目要求我们设计一种循环队列,满足FIFO原则且队尾被连接在队首之后。 题目中介绍循环队列的好处是可以重复利用空间,所以我们很容易想到在初始化时即开辟指定大小的空间,之后便不需要再开辟空间,只需后续销毁即可。 首先我们要选择

    2024年04月17日
    浏览(11)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包