1、 队列的定义:
队列是一种特殊的线性表,在表的前端(front)进行删除操作,也称之为“出队”通常命名为pop(),而在表的后端(rear)进行插入操作,也称之为“入队”通常命名为push(),和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。队列的数据元素又称为队列元素。队列的主要特点:先进先出。
2、 队列抽象数据类型的接口:
// 队列抽象数据类型
public interface Queue<T> {
//返回队列长度
int size();
// 判断队列是否为空
boolean isEmpty();
// data 入队,添加成功返回true,否则返回false,可扩容
boolean add(T data);
// offer 方法可插入一个元素,这与add 方法不同,该方法只能通过抛出未经检查的异常使添加元素失败。而不是出现异常的情况,例如在容量固定(有界)的队列中,NullPointerException:data==null时抛出
boolean offer(T data);
//返回队头元素,不执行删除操作,若队列为空,返回null
T peek();
// 返回队头元素,不执行删除操作,若队列为空,抛出异常:NoSuchElementException
T element();
// 出队,执行删除操作,返回队头元素,若队列为空,返回null
T poll();
//出队,执行删除操作,若队列为空,抛出异常:NoSuchElementException
T remove();
// 清空队列
void clearQueue();
}
3、 队列入队(data 入队,添加成功返回true,否则返回false,可扩容)
//元素入队
public boolean add(T data) {
//判断是否满队
if (this.front==(this.rear+1)%this.elementData.length){
ensureCapacity(elementData.length*2+1);
}
//添加data
elementData[this.rear]=data;
//更新rear指向下一个空元素的位置
this.rear=(this.rear+1)%elementData.length;
size++;
return true;
}
//拓展容量
public void ensureCapacity(int capacity) {
//如果需要拓展的容量比现在数组的容量还小,则无需扩容
if (capacity<size)
return;
T[] old = elementData;
elementData= (T[]) new Object[capacity];
int j=0;
//复制元素
for (int i=this.front; i!=this.rear ; i=(i+1)%old.length) {
elementData[j++] = old[i];
}
//恢复front,rear指向
this.front=0;
this.rear=j;
}
4、 队列出队
//元素出队
public T poll() {
T temp=this.elementData[this.front];
this.front=(this.front+1)%this.elementData.length;
size--;
return temp;
}
5、顺序队列的存储结构:
以下有6个存储空间的顺序队列动态示意图:
顺序队列在我们的使用过程中因多次入队列和出队列操作后出现的虽有存储空间但不能进行入队操作的情况,这就造成了顺序队列的“假溢出”的问题。如何解决“假溢出”这个问题呢?其实可以采用以下几种方法解决这个问题。
(1)、采用顺序循环队列;
(2)、按最大可能的进队操作次数设置顺序队列的最大元素个数;(最差的方法)
(3)、修改出队列算法,使每次出队列后都把队列中剩余数据元素向队头方向移动一个位置;
(4)、修改入队列算法,增加判断条件,当假溢出时,把队列中的数据元素向队头移动,然后完成入队列操作。
顺序循环队列的基本原理:把顺序队列所使用的存储空间构造成一个逻辑上首尾相连的循环队列。当rear和front达到maxSize-1后,在前进一个位置就自动到0。那么问题有来了,在顺序循环队列中,队列为空的特征是front=rear;队列为满是也会是front=rear;那如何区分开来呢?解决方法:第一种,使用一个计数器记录队列中元素个数(队列的长度);当count>&&rear == front时,队列为满;当count == 0时,队列为空。第二种,设标志位,出队时置0,入队时置1,则可识别当前front=rear属于那种情况;当tag == 1 && rear=front时,为队满;当tag == 0 && reat== front时,为队空;第三种,少用一个存储单位;当front==(rear+1)%maxSize时,为队满;当rear==front时,为队空。