队列(queue)是一种采用先进先出(FIFO)策略的抽象数据结构,即最先进队列的数据元素,同样要最先出队列。队列跟我们排队买票一样,先来排队的肯定先买票,后来排队的的后买到票。队列如下图所示:
队列有两个重要的概念,一个叫队头,一个叫队尾,队头指向的是第一个元素,而队尾指向的是最后一个元素。队列跟栈一样也是访问受限制的,所以队列也只有两个主要的操作:入队(enqueue)操作 和 出队(dequeue)操作 。入队操作就是将一个元素添加到队尾,出队操作就是从队头取出一个元素。
队列的底层实现可以用数组和链表,基于数组实现的队列叫作顺序队列,基于链表实现的队列叫作链式队列,下面我们分别用数组和链表来简单的实现这两种队列。
基于数组的队列
不管使用那种方式来实现队列,都需要定义两个指针分别指向队头和队尾,本文中我们用head指向队头,tail指向队尾,后面的示例中这将默认使用这个,有特殊的地方我会进行说明,先来看看顺序队列的入队、出队操作。
图中可以看出,入队时,队尾往后移动,队头保持不变,出队是队头往后移动,队尾保持不变。入队、出队操作的逻辑都比较简单,可能你有疑问的地方是:出队时为什么队头要往后移动而不是一直指向数组下标为0的位置? 为什么呢?如果我们保持队头一直指向数组下标为0的位置,那每次出队操作后,后面的数据都需要往前挪一位,换句话说每次出队操作都需要进行数据迁移,而数据迁移的代价比较大,每次数据迁移的时间复杂度为O(n),这样会极大的影响队列的使用性能。如果我们出队时,队头往后移动一位,这样我们就避免每次出队都进行数据迁移,我们只需要在只有在tail等于数组大小且head不等于0时,进行一次数据迁移,将已经出队留下的空间继续供入队时使用。下图是数据迁移的过程:
数据迁移时,从head位置开始的数据都需要往前移动head位,这样就把出队后的空间腾出来,供后续入队操作使用。
基于数组的队列实现代码:
/** * 基于数组的队列 */public class ArrayQueue { // 存放数据的数组 pr