详解循环队列

循环队列的定义及特点

循环队列是一种基于数组实现的队列数据结构,其特点是队尾指针可以循环回到数组的起始位置。

循环队列的定义包括以下几个关键属性:
1. 队列的容量:即数组的长度,表示队列可以存储的元素个数。
2. 队头指针(front):指向队列中第一个元素的位置。
3. 队尾指针(rear):指向队列中最后一个元素的下一个位置。

循环队列的特点包括:
1. 利用数组实现:循环队列使用数组作为底层数据结构,可以通过索引直接访问元素,具有高效的随机访问性能。
2. 循环利用空间:当队尾指针到达数组末尾时,如果队头指针仍然指向数组的起始位置,说明队列已满,此时可以将队尾指针循环回到数组的起始位置,实现空间的循环利用。
3. 避免元素搬移:在普通队列中,当队列头部有元素出队后,为了保持队列的连续性,需要将后续元素向前搬移。而在循环队列中,由于队尾指针可以循环回到数组起始位置,可以直接将新元素插入到队尾,无需搬移元素,提高了入队操作的效率。
4. 判空和判满条件:循环队列的判空条件是队头指针等于队尾指针,判满条件是队尾指针的下一个位置等于队头指针。这样可以避免队列为空时无法区分是队列满还是空的问题。 

 

 循环队列的操作

  • 初始化
  • 入队
  • 出队
  • 判空
  • 判满
  • 获取队列大小
  • 输出队列

 代码实现

初始化
/*循环队列初始化*/
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 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 isfull(CirclesQueue* Q)
{
	return (Q->rear + 1) % MAXSIZE == Q->front ? 1 : 0;
}
队列元素个数
/*计算队列中的元素个数*/
int size(CirclesQueue* Q) {
	return (Q->rear - Q->front + MAXSIZE) % MAXSIZE;
}

/*获取队列的首元素*/
int frontElement(CirclesQueue* Q, DataType* x) {
	if (isempty(Q)) {
		printf("队列为空!100002\n");
		return 100002;
	}
	*x = Q->data[(Q->front + 1) % MAXSIZE];
	return 0;
}
队列首元素
/*获取队列的首元素*/
int frontElement(CirclesQueue* Q, DataType* x) {
	if (isempty(Q)) {
		printf("队列为空!100002\n");
		return 100002;
	}
	*x = Q->data[(Q->front + 1) % MAXSIZE];
	return 0;
}
输出队列元素
/*输出队列中的所有元素*/
void printfQueue(CirclesQueue* Q) {
	int i = (Q->front + 1) % MAXSIZE;

	printf("队列元素:");

	while (i != (Q->rear + 1) % MAXSIZE) {
		printf("%d ", Q->data[i]);
		i = (i + 1) % MAXSIZE;
	}

	printf("\n\n");
}
 运行结果

 完整demo

main.c
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include "CirclesQueue.h"


int main(int argc, char* argv[])
{
	CirclesQueue Q;
	DataType x;
	int cmd;
	char yn;

	printf("-----------循环队列演示-----------\n");

	do
	{
		
		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(" 0. 退出\n");
		printf(" 请选择(0~8):");
		scanf("%d", &cmd);
		switch (cmd)
		{
		case 1:
			init(&Q);
			printf("队列已初始化!\n\n");
			break;
		case 2:
			printf("请输入要入队的元素x=");
			scanf("%d", &x);
			if (!enqueue(&Q, x))
			{
				printf("元素x=%d已入队\n\n", x);
			}
			break;
		case 3:
			getchar();
			printf("确定要出队(出队会将删除对首元素, y or n)?");
			scanf("%c", &yn);

			if (yn == 'y' || yn == 'Y')
			{
				if (!dequeue(&Q, &x))
				{
					printf("队首元素【%d】已出队!\n\n", x);
				}
			}
			break;

		case 4:
			if (isempty(&Q)) {
				printf("队列为空!\n\n");
			}
			else {
				printf("队列不为空!\n\n");
			}
			break;
		case 5:
			if (isfull(&Q)) {
				printf("队列已满!\n\n");
			}
			else {
				printf("队列未满!\n\n");
			}
			break;

		case 6:
			printf("队列中的元素个数:%d\n\n", size(&Q));
			break;

		case 7:
			if (frontElement(&Q, &x) == 0) {
				printf("队首元素:%d\n\n", x);
			}
			break;

		case 8:
			printfQueue(&Q);
			break;

		}

	} while (cmd != 0);


	return 0;
}
CirclesQueue.h
#pragma once
/*
	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 size(CirclesQueue* Q);

/*获取队列的首元素*/
int frontElement(CirclesQueue* Q, DataType* x);

/*输出队列中的所有元素*/
void printfQueue(CirclesQueue* Q);
CirclesQueue.c
/*
	CirclesQueue.c
*/
#define _CRT_SECURE_NO_WARNINGS 1
#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 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 isfull(CirclesQueue* Q)
{
	return (Q->rear + 1) % MAXSIZE == Q->front ? 1 : 0;
}


/*计算队列中的元素个数*/
int size(CirclesQueue* Q) {
	return (Q->rear - Q->front + MAXSIZE) % MAXSIZE;
}

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

/*输出队列中的所有元素*/
void printfQueue(CirclesQueue* Q) {
	int i = (Q->front + 1) % MAXSIZE;

	printf("队列元素:");

	while (i != (Q->rear + 1) % MAXSIZE) {
		printf("%d ", Q->data[i]);
		i = (i + 1) % MAXSIZE;
	}

	printf("\n\n");
}

小结

1. 循环队列的定义:循环队列是一种基于数组实现的队列数据结构,其特点是队尾指针可以循环回到数组的起始位置。

2. 循环队列的实现:循环队列的实现需要定义队列的容量、队头指针和队尾指针等关键属性,并且需要考虑循环利用空间和避免元素搬移等问题。

3. 循环队列的操作:循环队列支持入队、出队、判空、判满等基本操作。入队操作需要将新元素插入到队尾,并且需要考虑队列已满的情况;出队操作需要将队头元素弹出,并且需要考虑队列为空的情况。

参考资料

详解循环队列-CSDN博客

百度

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值