当我们调用两次出队操作之后,队列中 head 指针指向下标为 2 的位置, tail 指针仍然指向下标为4的位置。
随着不停地进行入队、出队操作, head 和 tail 都会持续往后移动。当 tail 移动到最右边,即使数组中还有空闲空间,也无法继续往队列中添加数据了。这个问题该如何解决呢?
用数据搬移!但是,每次进行出队操作都相当于删除数组下标为 0 的数据,要搬移整个队列中的数据,这样出队操作的时间复杂度就会从原来的 O(1) 变为 O(n)。能不能优化一下呢?
我们在出队时可以不用搬移数据。如果没有空闲空间了,我们只需要在入队时,再集中触发一次数据的搬移操作。借助这个思想,出队函数 pop() 保持不变,我们稍加改造一下入队函数 push() 的实现,就可以轻松解决刚才的问题了。
2、循环队列
我们刚才用数组来实现队列的时候,在 tail == n 时,会有数据搬移操作,这样入队操作性能就会受到影响。那有没有办法能够避免数据搬移呢?
我们来看看循环队列的解决思路。循环队列,顾名思义,它长得像一个环。原本数组是有头有尾的,是一条直线。现在我们把首尾相连,扳成了一个环。
我们可以看到,图中这个队列的大小为 8,当前 head=4, tail=7。当有一个新的元素 a 入队时,我们放入下标为 7 的位置。
但这个时候,我们并不把 tail 更新为8,而是将其在环中后移一位,到下标为 0 的位置。
当再有一个元素 b 入队时,我们将 b 放入下标为 0 的位置,然后 tail 加 1 更新为 1。
所以,在 a, b 依次入队之后,循环队列中的元素就变成了下面的样子: