Java实现循环队列(可以自动扩容)
先声明接口interface Queue<E>
//适用泛型
public interface Queue<E> {
int getSize();
boolean isEmpty();
void enqueue(E e);//入队
E dequeue();//出队
E getFront();//获得队首元素
}
class LoopQueue<E>
实现接口,测试也放在里面了
/**
* @author yinglongwu
*/
//循环队列
public class LoopQueue<E> implements Queue<E> {
private E[] data;
private int front,tail;
private int size;
public LoopQueue(int capacity) {
//+1是因为要故意浪费一个空间,来判断循环队列是否满了
data = (E[])new Object[capacity+1];//创建一个对象数组
front = 0;
tail = 0;
size = 0;
}
public LoopQueue() {
this(10);
}
//获取数组容量
public int getCapacity() {
return data.length-1;
}
//获取当前数组的元素个数
@Override
public int getSize() {
return size;
}
//如果队首和队尾指向的位置相同则为空
@Override
public boolean isEmpty() {
return front == tail;
}
//入队
@Override
public void enqueue(E e) {
//队尾对队列的容量取余,使队列循环起来(+1就是浪费的一个空间用来判断是否满了)
if ((tail+1)%data.length == front) {//如果循环队列满了
resize(getCapacity()*2);//扩容
}
data[tail] = e;
tail = (tail+1)% data.length;
size++;
}
//出队
@Override
public E dequeue() {
if (isEmpty()) {
throw new IllegalArgumentException("Cannot dequeue from an enpty queue.");
}
E ret = data[front];
//下面这句可加可不加,加上之后,java会自动回收,不加上就等下次这个位置指向新的对象,才回收这次的对象
data[front] = null;//loitering objects != memory leak 闲逛的对象不等于内存泄漏。
front = (front+1)%data.length;
size--;
//如果当前队列中元素个数等于数组的1/4,队列容量缩小1/2(减小复杂度震荡),可以节约空间
if (size == getCapacity() / 4 && getCapacity()/2!=0) {
resize(getCapacity()/2);
}
return ret;
}
//获取队首元素
@Override
public E getFront() {
if (isEmpty()) {
throw new IllegalArgumentException("Queue is empty.");
}
return data[front];
}
private void resize(int newCapacity) {
E[] newData = (E[])new Object[newCapacity + 1];
for(int i=0;i<size;i++) {
//将原来的循环队列里的元素从队首开始,依次放到新循环队列里
newData[i] = data[(i+front)%data.length];
}
data = newData;
front = 0;
tail = size;
}
//重写toString方法,可以更方便的显示队列信息
@Override
public String toString() {
StringBuilder res = new StringBuilder();
res.append(String.format("Queue: size = %d, capacity = %d\n",size,getCapacity()));
res.append("front [");//表明队首
for (int i = front; i != tail; i=(i+1)%data.length) {
res.append(data[i]);
//如果不是最后一个元素
if ((i+1)%data.length != tail) {
res.append(", ");
}
}
res.append("] tail");//表明队尾
return res.toString();
}
//测试
public static void main(String[] args) {
LoopQueue<Integer> queue = new LoopQueue<Integer>();
for (int i = 0; i < 10; i++) {
queue.enqueue(i);//入队
System.out.println(queue);
if (i%3==2) {//每三个元素出队一次
queue.dequeue();
System.out.println(queue);
}
}
}
}
测试结果