文章目录
前言
阅读本文前,最好先学习顺序表和栈的基本操作和实现原理,也就是弄清楚数组和栈的原理,点击Java实现基本数据结构(一)——数组,Java实现基本数据结构(二)——栈。先学习前置内容,学习效果更好哦!
队列简介
在数据结构中,队列和栈(Java实现基本数据结构(二)——栈)类似,也是一种线性表的结构。不同的地方在于栈只允许数据从一端进行插入和删除,而队列(Queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。根据这一种操作限制,我们将队列入队(插入操作)的一端称为队尾,出队(删除操作)的一端称为队首。所以队列也被称作为先进先出表(FIFO:First In First Out)。如下面图片所示,展示了一个队列的结构示意,入队和出队的操作示意:
图1 队列结构示意
图2 出队操作示意
图3 入队操作示意图
初识队列的应用
队列在计算机系统中也是一个应用非常广泛的数据结构。队列在设计程序中用的非常频繁,比如用用户用键盘输入内容后在显示器上显示出来这一过程,其实就是对列的典型应用,比如你输入了一个英文单词god,应用队列可以让显示和你的输入顺序一致,先输入的先输出,否则显示出dog可就真让人恼火了。
还有,我们会在用电脑时,偶尔会出现电脑处于疑似死机的状态,鼠标点什么似乎都没用,双击任何快捷方式都不动弹。就当你失去耐心,打算重启时。突然他像酒醒了一样,把你刚才点击的所有操作全部按顺序执行一遍。这其实是因为操作系统中的多个程序因需要通过一个通道输出,而按先后次序排队等待造成的。
在队列这种数据结构的具体实现上,一般也有两种实现方式:线性存储和链接存储(链表)。也就是使用数组和链表这两种数据结构都可以实现队列。
下面我们分别对这两种方法进行实现。
在Java中使用线性存储实现队列结构
在Java语言中,使用线性存储实现队列,和栈的实现思路一样,实际上就是使用数组这样一种结构,并对其操作进行限制来实现队列。也就是说实际上,对比数组,线性存储队列对应的操作就是数组的子集。
也就是说,我们实际上可以把队列这种结构看成一个特殊的数组,这个数组只能从一端添加元素,这一端称之为队尾(rear);却只能从另外一端取出元素,这一端称之为队首(front)。
和数组一样,线性存储的队列在使用时是静态分配的,就是使用的时候,内存已经以数组的形式开辟了一段空间,所以在初始化的时候,我们需要给定一个长度。
设计队列的功能
根据队列这种数据结构的特点,在队列的实现上,我们只需要设计以下几个功能即可:
(1)入队(enqueue)操作:将一个元素插入队列中,实际上就是插入数组的尾部。
(2)出队(dequeue)操作:将队首元素出队,实际上就是将数组头部的元素删除,并返回这个元素。
(3)查看队首元素(getFront)操作:将队首的元素返回给用户,实际上就是返回数组头部元素。
(4)返回栈的元素个数。
(5)判断栈是否为空。
因为我们前面说过,队列这种数据结构可以有两种实现方式,一种是线性存储,即通过数组实现;一种是链接存储,即通过链表实现。为了方便后续的实现,我们首先定义一个Queue接口,后面分别用数组和链表来实现这个接口即可。
实现Queue接口
按照上一小节的设计,我们直接在接口中约定这些功能即可。
public interface Queue<E> {
int getSize();
boolean isEmpty();
void enqueue(E e);
E dequeue();
E getFront();
}
通过数组实现Queue接口
为了更好的让本系列文章之间更好的串联知识点,本节实现的线性存储队列,将不使用JDK提供的ArrayList,使用Java实现基本数据结构(一)——数组中已经实现好的ArrayList类作为队列的存储结构。实际上,使用JDK提供的ArrayList类实现队列的方法是一样的,大家可以自行练习。
由于队列的功能比较简单,而且和栈的操作类似,这里直接对队列进行代码实现,相关细节在注释中体现。
public class ArrayQueue<E> implements Queue<E> {
// 泛型
// 定义一个数组用来存储队列中的元素
private ArrayList<E> array;
// 无参构造,直接使用ArrayList类中定义的无参默认值
public ArrayQueue() {
array = new ArrayList<E>();
}
// 有参构造,指定初始队列容量
public ArrayQueue(int capacity) {
array = new ArrayList<E>(capacity);
}
// 返回栈的元素个数,其实就是返回array的元素个数,调用array中的getSize()方法即可
@Override
public int getSize() {
return array.getSize();
}
// 返回栈的总体容量大小,同上,就是返回array的容量空间
public int getCapacity() {
return array.getCapacity();
}
// 返回栈是否为空,其实就是返回array是否为空,调用array中的isEmpty()方法即可
@Override
public boolean isEmpty() {
return array.isEmpty(