静态队列实现

本文介绍了循环队列的概念,探讨了为何静态队列必须是循环队列,详细解释了入队(EnQueue)和出队(DeQueue)的伪算法,并提供了判断队列满与空的方法。通过郝斌老师的教程实例,一步步解析队列操作原理。
摘要由CSDN通过智能技术生成
/*
	2022.05.14
	目的:
		理解简单的队列相关知识
	功能:
		静态队列,利用数组完成出队、入队
	理论:
		1.线性结构的队列,实现“先进先出”的存储结构;
		2.分类-链式队列(链表实现)和静态队列(数组实现),链式队列相较于静态队列简单些;
		3.链式队列-front 指向第一个元素,rear 永远指向最后一个元素的下一个元素,与栈区分开来;
		4.静态队列-数组实现,是在数组原有的一些功能上进行增减;
		5.静态队列通常都必须是循环队列;
		6.弄清楚循环队列需要弄清以下问题:
			a.静态队列为什么必须是循环队列?
			  因为静态队列是用数组实现的,那么由于数组的局限性,所以在使用的过程中,由于指针的移动,存在对数组空间的浪费;
			
			b.循环队列至少需要几个参数实现?
			  -front 与 rear 2个参数来确定

			c.循环队列各个参数的含义?
			  -两个参数在不同的场景有不同的含义
			  -建议初学者先记住,然后慢慢体会
				(1).队列初始化
					  front 与 rear 的值都是零
				(2).队列非空
					  front 代表的队列的第一个元素
					  rear  代表的队列的最后一个有效元素的后一个元素
				(3).队列空
					  front 与 rear 相等,但是不一定是零

			d.循环队列入队伪算法讲解?
				入队伪算法演示:
					1.将值存入“rear”所代表的位置;
					2.rear = rear + 1; //错误写法,当rear = 5时,加1越界; rear = (rear + 1)%数组的长度 //正确写法;

			e.循环队列出队伪算法讲解?
				出队伪算法演示:
					1.保存出队的值;
					2.front = (front + 1)%数组的长度;

			f.如何判断循环队列是否为空?
				front 与 rear 相等,队列为空

			g.如何判断循环队列是否已满?
				预备知识:
					front的值可能比rear大,
					front的值可能比rear小,
					当然也可能相等

				两种方式:
					1.多增加一个标识参数;
					2.少用一个元素,比如队列一共只能存储n个元素,那么现再存储到n-1个就不存储了。
					  如果rear与front的值紧挨着,则队列已满,实现的伪代码如下:
					  if((rear+1)%数组长度 == front)
							已满
					  else
							不满
*/	                  

#include <stdio.h>
#include <malloc.h>

typedef struct Queue /* 定义一个新的数据类型 */
{
	int* pBase;
	int iFront;
	int iRear;
}QUEUE;

void InitQueue(QUEUE *pQPara);        /* 初始化队列       */
bool EnQueue(QUEUE *pQPara, int val); /* 在某个队列入队   */
void Traverse(QUEUE *pQPara);         /* 对队列进行遍历   */
bool FullQueue(QUEUE *pQPara);        /* 判断队列是否为空 */
bool DeQueue(QUEUE* pQPara,int* pDeQueueVal);  /* 在某个队列进行出队 */
bool EmptyQueue(QUEUE* pQueue);       /* 判断队列是否为空 */

int main(void)
{
	QUEUE Q; /* 只是定义了一个QUEUE数据类型的变量,并没有对这个变量进行初始化 */
	int iTampVal; /* 存储出队值的变量 */

	InitQueue(&Q);

	EnQueue(&Q,1);
	EnQueue(&Q,2);
	EnQueue(&Q,3);
	EnQueue(&Q,4);
	EnQueue(&Q,5);

	Traverse(&Q);

	if (DeQueue(&Q, &iTampVal))
	{
		printf("出队成功,出队元素为:%d\n", iTampVal);
	}
	else
	{
		printf("出队失败\n");
	}
	Traverse(&Q);


	if (DeQueue(&Q, &iTampVal))
	{
		printf("出队成功,出队元素为:%d\n", iTampVal);
	}
	else
	{
		printf("出队失败\n");
	}
	Traverse(&Q);


    return 0;
}

void InitQueue(QUEUE *pQPara) /* 因为你在初始化的过程中需要改变结构体变量中的值,所以传进来的是结构体变量的地址 */
{
	pQPara->pBase = (int* )malloc(sizeof(int)*6); /* 申请一个含有6个整型空间的数组,并且数组的首地址返回给 pBase */
	pQPara->iFront = 0; /* 赋值第一个元素的下标 */
	pQPara->iRear = 0;  /* 同上 */

	return;
}

bool FullQueue(QUEUE* pQPara) /* 判断队列是否满 */
{
	if ((pQPara->iRear + 1)%6 == pQPara->iFront) /* 判断为满的算法 */
	{
		return true;
	}
	else
	{
		return false;
	}
}

bool EnQueue(QUEUE *pQPara, int val) /* 入队操作 */
{
	if (FullQueue(pQPara))  /* 如果队列已满 */
	{
		return false; /* 返回错误 */
	}
	else
	{
		pQPara->pBase[pQPara->iRear] = val;    /* 入队将值放在 pQPara->iRear*/
		pQPara->iRear = (pQPara->iRear + 1)%6; /* 移动到下一个位置,但是由于是循环的所以利用取余的操作解决这一问题  */
		return true; /* 返回正确 */
	}
}

bool EmptyQueue(QUEUE* pQueue) /* 判断队列是否为空 */
{
	if (pQueue->iFront == pQueue->iRear)  /* 如果队尾元素下表和队首元素下标相等  */
	{
		return true;
	}
	else
	{
		return false;
	}
}

bool DeQueue(QUEUE* pQPara, int* iDeQueueVal) /* 出队操作 */
{
	if (EmptyQueue(pQPara)) /* 判断为空则没有元素可以出队 */
	{
		return false;
	}
	else
	{
		*iDeQueueVal = pQPara->pBase[pQPara->iFront]; /* 要出队的值保存下来 */
		pQPara->iFront = (pQPara->iFront + 1) % 6;    /* 移动到下一个位置,但是由于是循环的所以利用取余的操作解决这一问题 */
		return true;
	}
}

void Traverse(QUEUE* pQPara) /* 对队列进行遍历 */
{
	int iTampVal = pQPara->iFront; /* 将第一个元素的序号赋值给iTampVal */

	while (iTampVal != pQPara->iRear) /* 当这两个序号不相等的时候,说明还没有遍历完成 */
	{
		printf("%d ", pQPara->pBase[iTampVal]);
		iTampVal = (iTampVal + 1) % 6; /* 移动到下一个位置,但是由于是循环的所以利用取余的操作解决这一问题 */
	}

	printf("\n");
}

/*
	程序运行结果:
		1 2 3 4 5
		出队成功,出队元素为:1
		2 3 4 5
		出队成功,出队元素为:2
		3 4 5
*/

理解:

循环队列的原因

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

循环队列入队伪算法

在这里插入图片描述

循环队列出队伪算法

在这里插入图片描述

如何判断队列已满

在这里插入图片描述
在这里插入图片描述

原创:参考 郝斌老师系列课程

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

軒邈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值