本文的主要内容就是利用数组[]实现双向队列,当然,Java中有比较丰富的容器可以直接使用,实现类似的功能容器有助于我们更深入的学习好了解相关知识。
现在就开始一步一步讲解如何实现。
1、双向队列的功能
首先,我们既然要实现该功能,就必然要把需求梳理清楚,我们要实现的容器到底有哪些功能。我们实现的队列主要功能如下:
入队列(push)
出队列(pop)
队首入队列(unshift)
队首出队列(shift)
获取队列中某个元素(get)
将值插入队列某个位置(insert)
移除队列中指定位置的值(remove)
迭代器(iterator) 所以,我们可以定义队列的接口如下:
package LinearList;
import java.util.Iterator;
public interface LinearList<E> {
//获取队列指定位置元素
public E get(int i);
//获取队列长度
public int getSize();
//判断队列是否为空
public boolean isEmpty();
//队列指定位置插入元素
public boolean insert(int i, E o);
//移除指定位置元素
public boolean remove(int i);
//队尾入队列
public boolean push(E o);
//队首入队列
public boolean unshift(E o);
//队尾出队列
public E pop();
//队首出队列
public E shift();
//迭代器
public Iterator<E> iterator();
}
定义了一个泛型接口,方法含义已在代码中注释,不解释了。 下面就贴出具体实现类,并解释其含义。
package LinearList.imp;
import LinearList.*;
import com.sun.istack.internal.NotNull;
import java.util.*;
/**
* 数组实现线性表
* author: xubaodian
* time: 2018/9/25
* @param
*/
public class ArrayLinearList<E> implements LinearList<E> {
//采用数组实现队列,初始数组长度为8,
private int Len = 8;
//队列长度,队列长度小于等于数据长度
private int count = 0;
//数组,是队列的容器,用来保存队列元素
private Object []arrayList;
public ArrayLinearList() {
arrayList = new Object[this.Len];
}
//获取队列中的指定元素,若索引大于队列长度,则抛出异常
@Override
public E get(int i) {
if (i < this.count) {
return (E)this.arrayList[i];
} else {
throw new ArrayIndexOutOfBoundsException("索引超出队列长度");
}
}
//获取队列长度
@Override
public int getSize() {
return this.count;
}
//判断队列是否为空
@Override
public boolean isEmpty() {
if (this.count == 0) {
return true;
}
return false;
}
//队列指定位置插入元素
@Override
public boolean insert(int i, E o) {
if (i <= this.count) {
for(int j = this.count; j > i ; j--) {
this.arrayList[j] = this.arrayList[j - 1];
}
this.arrayList[i] = o;
this.count++;
this.expandArray();
return true;
} else {
throw new ArrayIndexOutOfBoundsException("索引超出队列长度");
}
}
//移除指定位置元素
@Override
public boolean remove(int i) {
if (i < this.count) {
for (int j = i; i < this.count - 1; j++) {
this.arrayList[j] = this.arrayList[j + 1];
}
this.count--;
return true;
} else {
throw new ArrayIndexOutOfBoundsException("索引超出队列长度");
}
}
//队尾压入数组
@Override
public boolean push(E o) {
this.arrayList[this.count++] = o;
this.expandArray();
return true;
}
//队首压入数组
@Override
public boolean unshift(E o) {
for(int i = this.count; i > 0; i--) {
this.arrayList[i] = this.arrayList[i - 1];
}
this.count++;
this.arrayList[0] = o;
this.expandArray();
return true;
}
//队尾出数组
@Override
public E pop() {
if (this.count > 0) {
return (E)this.arrayList[this.count--];
} else {
return null;
}
}
//队首出数组
@Override
public E shift() {
if (this.count > 0) {
Object tmp = this.arrayList[0];
for (int i = 0; i < this.count; i++) {
this.arrayList[0] = this.arrayList[i + 1];
}
this.count--;
return (E)tmp;
} else {
return null;
}
}
//数组容量扩充为原来的2倍,并将现有数组迁移入新的数组中
private void expand() {
this.Len *= 2;
Object [] array = new Object[this.Len];
for (int i = 0; i < count; i++) {
array[i] = this.arrayList[i];
}
this.arrayList = array;
}
//判断数组是否已满,若数组已满,则扩充数组
private void expandArray() {
if (this.count == this.Len) {
this.expand();
}
}
//返回迭代器
@Override
@NotNull
public Iterator<E> iterator() {
return new ArrayLinearList.Itr();
}
//迭代器私有类
private class Itr implements Iterator<E> {
int cursor = 0; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
public boolean hasNext() {
return cursor != count;
}
@SuppressWarnings("unchecked")
public E next() {
int i = cursor;
if (i >= count)
throw new NoSuchElementException();
cursor = i + 1;
return (E) arrayList[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
try {
ArrayLinearList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
}
利用数组实现队列,数组的初始长度为8,当数组已满,则新建数组,新数组容量为现有数字的2倍,并将现有数组元素迁移至新数组。
同时,为队列实现了跌代器,利用跌代器可遍历容器。
具体实现并不难,大家可根据代码,理解一下,有利于理解java容器知识,如有疑问,请给我留言。