顺序队列本质上是由顺序表实现的,但是每次出队一个元素,都需要将后续所有元素前
移,影响效率。
能否在出队时保持其他元素位置不变?可以,但是这样子的话,出队的元素多了,其顺
序表中当前队首元素之前会有很多闲置空间。
如何利用闲置空间?此处就需要将顺序表收尾相连,形成循环表。
我们把这种队列的这种头尾相接的顺序存储结构称为循环队列。
我们先定义一个队列接口:
public interface Queue <E> {
public int getSize(); //获取队列元素个数
public boolean isEmpty(); //判空
public void enqueue(E e); //入队
public E dequeue(); //出队
public E getFront(); //获取队首元素
public E getRear(); //获取对位元素
public void clear(); //清空队列
}
接着实现循环队列:
public class ArrayQueueLoop<E> implements Queue<E>{
private E[] data;
private int front; //头指针
private int rear; //尾指针
private int size;
public ArrayQueueLoop() {
this(10);
}
public ArrayQueueLoop(int capacity) {
data=(E[]) new Object[capacity+1]; //多定义一个空间存放尾指针
size=0;
front=0;
rear=0;
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return size==0;
}
@Override
public void enqueue(E e) {
if((rear+1)%data.length==front){ //尾指针可能在最后一个位置,需要将其移到队首再判断
throw new IllegalArgumentException("队列已满!");
}
data[rear]=e;
rear=(rear+1)%data.length; //入队尾指针在最后一位时需要跳至数组下标为零处
size++;
}
@Override
public E dequeue() {
E res=getFront();
front=(front+1)%data.length; //出队头指针在最后一位时需要跳至数组下标为零处
size--;
return res;
}
@Override
public E getFront() {
if(isEmpty()){
throw new IllegalArgumentException("队列为空!");
}
return data[front];
}
@Override
public E getRear() {
if(isEmpty()){
throw new IllegalArgumentException("队列为空!");
}
if(rear==0){ //尾指针此时在下标0处,取最后一位元素
return data[data.length-1];
}else{
return data[rear-1];
}
}
@Override
public void clear() {
front=0;
rear=0;
size=0;
}
@Override
public String toString() {
if(isEmpty()){
return "[]";
}
StringBuilder sb=new StringBuilder("[");
for(int i=front;i!=rear;i=(i+1)%data.length){ //for循环要注意
if((i+1)%data.length==rear){
sb.append(data[i]+"]");
}else{
sb.append(data[i]+",");
}
}
return sb.toString();
}
}