数据结构之顺序循环队列的基本操作(非常详细C语言版)

本文详细探讨了顺序循环队列的概念,包括为何使用int类型而非指针表示front和rear,如何判断队列满,%运算的作用,以及队列长度计算。通过实例解析了Q.rear=(Q.rear+1)%MAXQSIZE等关键操作,帮助理解循环队列的实现原理。
摘要由CSDN通过智能技术生成

----------------------✨🎉🎈==!!!热烈欢迎各位大佬!!!==🎈🎉✨---------------------

🍹作者: BooleanChar12

博客主页BooleanChar12的博客

💘很喜欢的一句话Because we all stand on the shoulders of giants.

🥂如有bug疑惑欢迎大家与我🤺

😍觉得博主文章写的不错的话,希望大家三连(🎉关注,🎉点赞,🎉评论),多多支持一下!!

--------------------------------------------------------------------------🍻==专栏回顾==🍻-------------------------------------------------------------------------------

Java(从入门到放弃) 🍉数据结构(从放弃到入门) 🍒Android开发(从入门到入土)
🍇计算机组成原理(从1到0) 🍑计算机网络(从上网到退网) 🥝操作系统(从0到0.1)
🍎C语言练习题 🏆Leetcode(狂刷笔记) 🌺微信小程序开发日记

写在前面:因初学数据结构,读者如发现有错误或者疑惑,可评论私信,一起交流,如觉得写得不错,还请点赞,谢谢!

1.排忧解惑🌈:

1.为什么front和rear是int类型的变量却还要叫指针?

个人看法:是因为顺序循环队列指向的是一块连续的内存空间(可以看作一个数组空间),
在操作队列的时候只存在地址加一位或者减一位的情况,
使用指针来表示在访问的时候反而更加麻烦,不如用数组的下标(就是这里定义的int front表示的其实是base[]数组的下标)来表示
当然也可以用指针来表示,下面相应的代码也要改变,只是对于操作这种连续且每次只会+1,-1的地址来说
用这种方式访问更加方便

2.如何判断循环队列是否满了?

​ 由于顺序循环队列的队空和队满的条件都是Q.frontQ.rear,就无法判断到底是队空还是队满,我们就得重新想一个判断条件
​ 解决方法:1.设计一个变量记录队中元素个数,个数为0则队空,个数为MAXQSIZE则队满
​ 2.设计一个标志以区别队空和队满
​ 3.少用一个队列格子,即用(Q.rear+1)%MAXQSIZEQ.front来判断,即下一个rear所在的位置与对头front所在位置相等
​ 注:下面代码采用的是第三种方式判断队空或者队满

3.浅谈为什么要用到%运算?

个人看法:1.%取模运算的本质是让运算后的结果落入0~这个模数中,
其实就是循环减去一个数直到被模的数小于模数(即被模的数不够减去1*模数的时候循环终止),然后将被模的数返回作为模运算的结果
为什么这么说呢,举例:20%6=2

				1.循环开始:第一次		20-6=14
				2.			第二次		14-6=8
				3.			第三次		8-6=2
				4.循环终止:第四次		2-6发现减不过,终止循环,把2返回作为本次模运算的结果 
			
			再比如:1%6=1 2%6=2 3%6=3 4%6=4 5%6=5 6%6=0 7%6=1 8%6=2 9%6=3......
			不难看出,无论哪个正整数%6,最后的结果一定都在[0,6]这个区间内,
			而且随着正整数的增大,结果是每次+1,并且循环的,即0,1,2,3,4,5,6,0,1,2,3,4,5,6,0......
			所以我们巧妙利用%运算的这个特点,把实际的线性顺序内存可以当作循环顺序内存使用 

4.解读Q.rear = (Q.rear+1)%MAXQSIZE

​ 1.如果 Q.rear+1<MAXQSIZE时,即没有假溢出,则运算结果就等于Q.rear+1,即rear正常的rear++
​ 2.如果 Q.rear+1>MAXQSIZE之后,即发生假溢出,则运算结果就会从进入新的[0,100]的循环,%运算保证每次rear++后的结果落在[0,100]之间
​ 3.下面代码中的 Q.front = (Q.front+1)%MAXQSIZE同理

5.为什么队列的长度不是Q.rear-Q.front而是(Q.rear-Q.front+MAXQSIZE)%MAXQSIZE?

1.普通队列的长度:length = Q.rear-Q.front
2.循环队列的长度: (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE
3.个人认为,(Q.rear-Q.front+MAXQSIZE)%MAXQSIZE其实就是这个if语句的整合:
	 	if((Q.rear-Q.front)>0) {     
		printf("当前队列的长度:%d\n",Q.rear-Q.front);
	} else {
		printf("当前队列的长度:%d\n",Q.rear+MAXQSIZE-Q.front);
	}
	3.1如果Q.rear>Q.front,那队列长度就是Q.rear-Q.front
	3.2如果Q.rear<Q.front,那说明该队列处理了假溢出情况,
		   使得Q.rear的值小于Q.front的值,如果不循环,Q.rear的真实值应该是Q.rear+MAXQSIZE
		   举例说明:假设MAXQSIZE是6,Q.rear到达base[5],即Q.rear=5,再进行入队时,Q.rear的值应该为6+1=7,但是内存就那么大,指针也就那么移动, 
		   所以我们使用的是循环队列,使用%运算后相当于把7变成了0,这之间差了7-0=7,正好为MAXQSIZE
		   也就是说,如果不是循环队列,Q.rear的值应为Q.erar+MAXQSIZE=7 
		   所以这时候循环队列的长度应该是Q.rear+MAXQSIZE-Q.front 
	3.3有的人肯定还会疑惑:那Q.front的值也经过假溢出处理(即第一次循环后)呢?Q.front的值要不要加MAXQSIZE? 
		   说明:因为先入队才能出队,所以Q.rear的值肯定是先于Q.front的值,就是循环的时候,Q.rear的值是跑在Q.front的值之前的
		     	 如果Q.front和Q.rear的值都经过了一次循环,那么Q.front的值肯定是出队引起的变化,出队会导致队长-1,不用加MAXQSIZE 
4.了解了上述if语句,相信你也就理解了(Q.rear-Q.front+MAXQSIZE)%MAXQSIZE的含义 
	4.1如果Q.rear>Q.front,
		因为队列不满,Q.rear-Q.front的值一定小于1*MAXQSIZE,
		所以(Q.rear+MAXQSIZE-Q.front)的值一定大于1*MAXQSIZE,小于2*MAXQSIZE,
		所以(Q.rear+MAXQSIZE-Q.front)%MAXQSIZE的最终结果还是 Q.rear-Q.front
			eg:假设MAXQSIZE=6,某一状态时Q.rear=4,Q.front=2;(即队列入队4个元素后,出队2个元素,此时队长应为2)
				0<4-2<1*6
				0<4-2+6<2*6
				取模之后相当于把加的6给减去了,剩下的就是计算结果,即 4-2就是计算结果,也就是4-2就是队长  
	4.2如果Q.rear<Q.front,
		因为队列不满,Q.rear-Q.front的值一定大于-(1*MAXQSIZE),小于0 
		所以(Q.rear+MAXQSIZE-Q.front)的值一定大于0,小于1*MAXQSIZE,
	    所以(Q.rear+MAXQSIZE-Q.front)%MAXQSIZE的最终结果还是Q.rear+MAXQSIZE-Q.front
			eg:假设MAXQSIZE=6,某一状态时,Q.rear=2,Q.front=4;(即队列入队8个元素后,出队4个元素,此时队长应为4)
				-1*6<2-4<0
				0<2-4+6<1*6
				取模时发现2-4+6不够减1个6,所以2-4+6就是计算结果,即2-4+6就是队长   
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

BooleanChar12

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

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

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

打赏作者

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

抵扣说明:

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

余额充值