基本定义:一种特殊的线性表, 只允许在表的前端front进行删除操作, 只允许在后端rear 进行插入操作。进行插入的端叫做队尾,进行删除的一段叫做队头 。 ---- 先进先出的原则 FIFO
既然有固定的顺序操作 所以提供的大概有如下的操作:
* init 初始化 :通常是一个构造器, 用于创建一个空队列
* init 初始化 :通常是一个构造器, 用于创建一个空队列
* length : 返回队列中元素的个数
* insert : 向队尾rear 插入一个数据 length + 1
* delete : 在对头front 删除一个数据 length - 1
* 访问前端元素 : 返回front 端的数据元素,但是不删除它
* isEmpty() : 空 - true 否则 false
* 清空 clear :将队列清空
* insert : 向队尾rear 插入一个数据 length + 1
* delete : 在对头front 删除一个数据 length - 1
* 访问前端元素 : 返回front 端的数据元素,但是不删除它
* isEmpty() : 空 - true 否则 false
* 清空 clear :将队列清空
实现它的数据结构:采用一组地址连续的存储单元一次存放队列从rear --> front的所有数据元素。程序只需要front和rear两个整型变量来记录front和rear端的元素索引。顺序存储结构的队列叫做顺序队列(SequenceQueue)。
参考代码部分:
public class SequenceQueue<T> {
private int DEFAULT_SIZE = 20;
//记录数组的长度或者说容量
private int length;
//定义一个数组来存储这个队列的元素
private Object[] elementData;
//保存当前顺序队列的个数
private int front = 0;
private int rear = 0;
//根据默认的长度构建一个顺序队列
public SequenceQueue(){
this.length = DEFAULT_SIZE;
elementData = new Object[length];
}
//以一个初始元素建立顺序队列
public SequenceQueue(T data){
this();
elementData[0] = data;
rear ++;
}
//以一个初始元素和指定的长度建立顺序队列 data相当于指定的第一个元素, initSize 指定顺序队列底层数组的长度
public SequenceQueue(T data, int initSize){
this.length = initSize;
elementData = new Object[length];
elementData[0] = data;
rear ++;
}
//插入队列
public void insert(T data){
if(rear > length -1){
throw new IndexOutOfBoundsException("队列已满!");
}
elementData[rear++] = data;
}
//移除或者删除队列
public T remove(){
if(empty()){
throw new IndexOutOfBoundsException("空队列!");
}
//队列front端的元素值
T oldValue = (T)elementData[front];
//释放队列front端的元素
elementData[front++] = null;
return oldValue;
}
//判断是否为空队列
private boolean empty() {
// TODO Auto-generated method stub
return rear == front;
}
//获取队列大小
public int length(){
return rear - front;
}
//返回队头的元素
public T getElement(){
if(empty()){
throw new IndexOutOfBoundsException("空队列!");
}
return (T)elementData[front];
}
//清空队列
public void clear(){
//将底层的数组所有元素赋值为Null
Arrays.fill(elementData, null);
front = 0;
rear = 0;
}
public String toString(){
if(empty()){
return "[]";
}
else{
StringBuffer sb = new StringBuffer("[");
for(int i = front ; i < rear ; i ++){
sb.append(elementData[i].toString() + ", ");
}
int len = sb.length();
return sb.delete(len - 2, len).append("]").toString();
}
}
}
测试部分和截图:
public static void main(String[] args) {
SequenceQueue<String> sq = new SequenceQueue<String>();
sq.insert("aa");
sq.insert("bb");
sq.insert("cc");
sq.insert("dd");
System.out.println(sq);
System.out.println("输出队头元素:" + sq.getElement());
System.out.println("移除队头元素:" + sq.remove());
System.out.println(sq);
}
对于顺序队列来说,因为底层是使用数组存储队列元素,每个队列元素在数组中的位置是固定的,改变的只是rear和front的值而已。当rear的值等于数组的大小,再试图添加元素时,会引起队列已满的异常。但是此时的这个异常可以称为“假满”的现象,数组依旧有空位,只是程序加不进去。
解决方案:1.“整体搬家”。每次将元素移出队列的时候都将队列中的所有元素向front端移动一位。这种方式下front值永远保持为0,元素插入队列时rear + 1, 元素移出队列时rear - 1。但是很明显浪费时间。
2.“循环队列”。就是将存储区堪称首尾相连的环形区域,当达到数组最大长时, rear的值再次变为0。
此方法是我们接下来将要介绍的,请参看:
点击打开链接。
参考:
《疯狂java 突破程序员基本功的16课》
以上是这篇的主要内容,如有错误或需要改进之处,请指教。谢谢!