同普通数组实现的队列相比,普通数组的头结点和尾节点都是固定的,在进行移除的时候如果移除了一个节点,后面所有节点都需要进行移除操作,需要的时间复杂度更高
在环形数组中,确定了头尾指针的环形数组很好地解决了这一点
我们来看具体思路
有两个指针,在环形数组为空的时候它们都指向这个0索引
加入元素之后,尾指针后移一位,直到尾指针的 下一个和头指针重合,如图
在进行移除操作的时候,将头指针前进一位即可
isfull:当尾指针的下一个位置与头指针重合时,说明环形数组已经满了
用索引来表示的话每次让移动让tail+1,和数组长度取模即可,再和head的值进行判断
isempty:当尾指针与头指针重合的时候,说明环形数组为空
为了使下标可以为0到4循环,我们需要控制tail和head,所以我们可以这么表示
进行head和tail的迭代
在迭代器中,将初始节点定位为p=head,循环条件为p!=tail,因为tail指的是下一个存入元素的数组位置
我们来看方法实现
和之前的思路相近,我们多设置一个size记录元素个数,这个时候不需要牺牲一个存储容量,在isfull判断中直接通过比较size和数组长度,在非空判断中,判断size是否为0即可
关于迭代器遍历,我们需要再引入一个变量count,初始值赋值为0,循环条件是count<size,因为size代表元素个数
我们来看代码
我们还是设置头尾指针,我们以上图为例子,有一个长度为3的环形数组
我们一直将head和tail进行移动的时候递增,不再通过head和tail做处理来代表索引,而是通过将递增的head和tail进行计算来求索引,我们不再通过array[head]或者array[tail]代表元素值,而是通过
array[head%array.length]和array[tail%array.length]
在进行非空判断的时候,思路还是tail=head
在进行非满判断的时候,思路则是通过tail-head等不等于数组长度,无需牺牲一个存储空间。
我们来看代码
在方法三中,我们不对head和tail进行处理,而是放任其递增,因为int是有范围的,再超过tail的最大范围之后会报错,所以我们思考处理方法
第一种方法,通过转成长整型long避免越界报错,强制转型
但是所有涉及的数组都需要进行强制转型,会比较复杂
求模运算:
- 如果除数是2的n次方
- 那么被除数的后n位即为余数(模)
- 求被除数的后n位方法:与2^n-1次方进行按位与运算
修改如上
如果数组长度不是2的n次方,我们该如何应对呢
第一种方法直接抛出异常
我们可以根据这个规律直接抛出异常
第二种方法是修改传入参数
我们先看思路,假设传进来的数值是30
我们需要将30改成32,也就是找到最近的2的n次方等于32,
我们可以看到log2(30)大约是等于4.几,为了使其变成5,我们可以将log(30)+1,并将其强制转型为整型
又因为idea java语言中的Math包里面只有log10,所以我们可以使用换底公式
但是如果说本来这个数字就是2的n次幂的话再+1就会修改它的值,所以我们可以给传入的参数值进行-1处理,这样就可以很好的避免
在我们得到了n次幂的基础上,我们只需要对1进行左移即可(2^0=1)
代码如下
或者我们也可以直接利用一个公式
c-=1;
c|=c>>1;
c|=c>>2;
c|=c>>4;
c|=c>>8;
c|=c>>16;
c+=1;
代码如下
到此这篇环形队列(环形队列的优点)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/bcyy/77440.html