----------------------✨🎉🎈==!!!热烈欢迎各位大佬!!!==🎈🎉✨---------------------
🍹作者: 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=21.循环开始:第一次 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就是队长