循环队列的实现与优势

目录

一、循环队列的特点:

二、普通的队列的缺点:

三、循环队列实现原理:

四、循环队列是实现步骤:

1.循环队列的头文件: 

2.循环队列的源文件:

3.注意点: 


一、循环队列的特点:

是具有队头指针和队尾指针,指示队列元素所在的位置,避免删除元素时移动大量元素。它只能队尾插入元素、在队头删除元素,是先进先出(First In First Out)的线性表,先进入的元素出队,后进入的元素才能出队。相比普通的队列,元素出队时无需移动大量元素,只需移动头指针。循环队列适合处理用户排队等待的情况,但需要预先分配大量存储空间。其时间复杂度为读取时O(1),插入、删除时O(1)。

循环队列的优点:防止假溢出!循环队列可以有效地利用空间,避免了普通队列在出队操作后无法再次利用已出队的空间的问题。此外,循环队列还可以通过修改指针的位置实现逆序输出。 


二、普通的队列的缺点:

假溢出:前面的空间就无法利用。


三、循环队列实现原理:

是基于固定长度的数组实现。 并且会多开一个空间(区分满和空的情况)

循环队列是逻辑上循环,而不是物理上循环,物理上还是线性存储。

 我们把第二个圈当做满来看,目的是为了用front和rear来区分空和满。


四、循环队列是实现步骤:

1.创建循环链表并且初始化

2.销毁循环队列
3.队列入,出

4.判断队列是否为空

5.判断队列是否为满

6.输出队列内容(打印)

7.获取队列长度

8.获取队列头元素

9.获取队列尾元素


1.循环队列的头文件: 

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int CQDataType;
typedef struct CirQueue
{
	CQDataType* a;//指向数组的首元素
	int front;//指向头数据
	int rear;//指向尾数据的下一个位置
	int k;//实际存放的数据个数
}CQ;

//创建循环链表并且初始化
CQ* CreateQ(int n);

//销毁循环队列
void CirQueueDestry(CQ* cq);
//队列入,出
bool CirQueuePush(CQ* cq, CQDataType x);
bool CirQueuePop(CQ* cq);

//判断队列是否为空
bool CirQueueEmpty(CQ* cq);

//判断队列是否为满
bool CirQueueFull(CQ* cq);

//输出队列内容,打印
void CQPRINT(CQ* cq);

//获取队列长度
int CQSize(CQ* cq);

//获取队列头元素
CQDataType CQFrontElement(CQ* cq);

//获取队尾数据
int CirQueueRear(CQ* cq);

//销毁循环队列
void CirQueueDestroy(CQ* cq);

2.循环队列的源文件:

#define _CRT_SECURE_NO_WARNINGS 1
#include"CirQueue.h"
//创建循环链表并且初始化
CQ* CreateQ(int n)
{
	CQ* cq = (CQ*)malloc(sizeof(CQ));
	if (cq == NULL)
	{
		perror("malloc error");
		exit(-1);
	}
	CQDataType* tmp = (CQDataType*)malloc(sizeof(CQDataType) * (n + 1));
	if (tmp == NULL)
	{
		perror("malloc error");
		exit(-1);
	}
	cq->a = tmp;
	cq->front = cq->rear = 0;
	cq->k = n;
	return cq;
}

//销毁循环队列
void CirQueueDestry(CQ* cq)
{
	free(cq->a);
	free(cq);
}
//队列入,出
bool CirQueuePush(CQ* cq, CQDataType x)
{
	if (CirQueueFull(cq))
	{
		return false;
	}
	cq->a[cq->rear] = x;
	cq->rear++;
	cq->rear %= (cq->k + 1);
	return true;
}
bool CirQueuePop(CQ* cq)
{
	if (CirQueueEmpty(cq))
	{
		return false;
	}
	cq->front++;
	cq->front %= (cq->k + 1);
	return true;
}

//判断队列是否为空
bool CirQueueEmpty(CQ* cq)
{
	return cq->front == cq->rear;
}

//判断队列是否为满
bool CirQueueFull(CQ* cq)
{
	return (cq->rear+1)%(cq->k+1) == cq->front;
}

//输出队列内容,打印
void CQPRINT(CQ* cq)
{
	int szie = CQSize(cq);
	if (cq->front > cq->rear)
	{
		for (int i = cq->front; i < cq->k+1; i++)
		{
			printf("%d ", cq->a[i]);
		}
		for (int i = 0; i < cq->rear; i++)
		{
			printf("%d ", cq->a[i]);
		}
	}
	else
	{
		for (int i = cq->front; i < cq->rear; i++)
		{
			printf("%d ", cq->a[i]);
		}
	}
}

//获取队列长度
int CQSize(CQ* cq)
{
	if (cq->front > cq->rear)
	{
		return (cq->k) - (cq->front) + (cq->rear)+1;
	}
	else
	{
		return (cq->rear) - (cq->front);
	}
}

//获取队列头元素
CQDataType CQFrontElement(CQ* cq)
{
	if (CirQueueEmpty(cq))
	{
		return -1;
	}
	return cq->a[cq->front];
}

//获取队尾元素
int CirQueueRear(CQ* cq)
{
	if (CirQueueEmpty(cq))
	{
		return -1;
	}
	return cq->a[(cq->rear - 1 + cq->k + 1) % (cq->k + 1)];
}


3.注意点: 

1.入队列:判断队列是否为满,满的时候就不能入队列

                 考虑rear++时越界,需要让它变成最小值。

2.出队列:判断队列是否为空

                  也要考虑front--时越界,也要考虑循环问题

3.判空:rear==front

4.判满:rear+1==front(也要考虑循环问题) 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值