相当于前面讲过的数组模拟非环形队列(也就是一般队列),我们这里有如下的变化:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s3QhAoVh-1659252098562)(E:\非凡英才\数据结构(java)]\数据结构图解\数组模拟环形队列的实现示意图.png)
对于之前我们讲过的非环形队列来讲: 我们的maxSize即使队列底层数组的最大容量,还是队列的长度,但是这里我们对于环形队列来讲: 数组的最大容量 = 队列容量 + 1
不是队尾元素的下一个位置被留作了约束空间,而是队首元素的上一个位置被留作了约束空间
我们对于数组模拟环形队列过程中的队首指针和队尾指针都是不需要进行显示初始化的,因为在我们使用数组模拟环形队列的实现中我们的队首指针和队尾指针初始值都是0,而我们默认初始化的值就是0,所以就没有必要再次在构造器中或者初始化块(代码块)中进行一次显示的初始化
我们在往数组实现的队列中添加元素的时候要先判断队列是否已满,因为如果队列已经满了,这个时候就不能再添加元素了
我们在删除数组实现的队列中的元素的时候要先判断队列是否为空,如果队列都已经为空了,那么也就没有元素可删了
对于数组实现的环形队列来将我们队首指针和队尾指针后移的时候都要考虑越界的发生,所以就要进行取模
我们从数组模拟环形队列实现中如果要进行出队列的操作,这个时候一定注意,因为我们出队列是从队列的头部位置开始出队列,那么我们在出队列的时候一定要用到一个"临时变量",使用这个临时变量先将我们当前的front指向的元素保存到这个临时变量中,然后再进行指针后移,然后我们再将临时变量中存储的队列中被删除的元素返回
我们如果是数组模拟的环形队列,这个时候如果我们遍历显示队列中的数据,这个时候我们是从索引为front的位置开始遍历,因为我们的front是队首指针,指向的是循环队列中的第一个位置,并且我们要遍历队列中有效数据的个数次,那么我们如何求得队列中的有效数据个数?
在数组模拟环形队列中 : 索引越界位置 %(取模) 数组长度 = 索引实际位置
这里补充一个小算法:
移动次数 = 间隔数 + 1;
我们使用循环队列进行删除元素的操作的时候时间复杂度是一个O(n) —> 因为我们如果是使用数组实现了一个非循环队列 , 这个时候我们每次删除的时候都是从队首开始删除元素, 也就是从数组的头部开始输出元素 ,这个时候每次数组头部的元素被删除之后后面的所有位置的元素都要移动到前面来 ,这个时候时间复杂度就是O(n) , 但是我们如果是使用循环队列的时候就不会有这样的问题, 我们使用数组实现的循环队列在删除元素的时候永远都只需要执行一个front 后移的操作 ,不需要我们的元素前移, 因为我们的循环队列中的任意位置都可以作为头指针和尾指针的位置 , 那么也就是对于循环队列来讲我们每次删除元素的时候只需要进行一个front后移操作, 具体添加元素的时候直接队尾指针直接向后移动就可以了 , 经过我们循环处理之后队尾指针会跑到数组中队首指针的前面,而不会出现数组下标越界的问题
如果某种数据结构的底层实现是一个自定义数组类 , 这个时候如果我们的这个自定义数组类中实现了数组扩容的功能, 这个时候我们往这个数据结构中添加元素的时候就不用判断这个数据结构是否为满了 ,这个时候由于我们的底层数组类是可以进行一个自动扩容的, 所以这个时候当我们的此数据结构满的时候底层数组也就肯定是会满足我们的扩容条件 ,会进行一个扩容 , 但是如果我们的某种数据结构的底层实现是一个自定义数组,但是这个数组中没有扩容功能的时候我们的这个数据结构在添加元素的时候就要判断这个数据结构是否是满了 ,如果满了的时候就不能向这个数据结构中放置元素了