循环队列
数组队列的出队操作的复杂度是O(n),性能很差,解决方法就是使用循环队列(Loop Queue)
在循环队列中,需要对队为空和队为满的时候进行判断,为了区分队空和队满两个条件,需要浪费capacity一个空间,让rear指针一直指向一个空的位置;
当 rear= =front 时,队为空;
当 (rear+1)%n= =front (n为数字角标的最大值)时,队为满.
示意图如下:
循环队列实现
//循环队列
public class ArrayQueueLoop<E> implements Queue<E> {
private E[] data;
private int front;
private int rear;
private int size;
//无参构造函数
public ArrayQueueLoop(){
data= (E[]) (new Object[11]);//因为有一个空的空间
front=0;
rear=0;
size=0;
}
//获取长度
@Override
public int getSize() {
return size;
}
//判空
@Override
public boolean isEmpty() {
return size==0&&front==rear;
}
//进队
@Override
public void enqueue(E e) {
if((rear+1)%data.length==front){
resize(2*data.length-1);
}
data[rear]=e;
rear=(rear+1)%data.length;
size++;
}
//出队
@Override
public E dequeue() {
if(isEmpty()){
throw new IllegalArgumentException("队列空");
}
E ret=data[front];
front=(front+1)%data.length;
size--;
if(size<=(data.length-1)/4&&(data.length-1)/2>=10){
resize((data.length-1)/2+1);
}
return ret;
}
//改变数组长度
private void resize(int newLen){
E[] newData= (E[]) (new Object[newLen]);
int p=front;
int i=0;
while(true){
newData[i]=data[p];
i++;
p=(p+1)%data.length;
if(p==rear){
break;
}
}
front=0;
rear=size;
data=newData;
}
//获取队头元素
@Override
public E getFront() {
if(isEmpty()){
throw new IllegalArgumentException("队列为空");
}
return data[front];
}
//获取队尾元素
@Override
public E getRear() {
if(isEmpty()){
throw new IllegalArgumentException("队列为空");
}
return data[(rear-1+data.length)%data.length];
}
//清空队列
@Override
public void clear() {
data= (E[]) (new Object[11]);//因为有一个空的空间
front=0;
rear=0;
size=0;
}
//自定义格式打印元素
@Override
public String toString() {
StringBuilder sb=new StringBuilder();
sb.append(String.format("ArrayQueueLoop: %d/%d\n",size,data.length-1));
sb.append('[');
if(isEmpty()){
sb.append(']');
}else{
for(int i=front;i!=rear;i=(i+1)%data.length){
sb.append(data[i]);
if((i+1)%data.length==rear){
sb.append(']');
}else{
sb.append(',');
}
}
}
return sb.toString();
}
//迭代器
@Override
public Iterator<E> iterator() {
return new ArrayQueueLoopIterator();
}
private class ArrayQueueLoopIterator implements Iterator{
int p=front;
@Override
public boolean hasNext() {
return p!=rear;
}
@Override
public Object next() {
E ret=data[p];
p=(p+1)%data.length;
return ret;
}
}
}