循环队列相比于数组队列,最大的特点就是可以降低出队操作的时间复杂度,从O(n)将为O(1),降低移动的次数(不是完全不用移动),具体实现的原理就是队列在出队一个队首元素以后,队列中剩下的元素的相互间的顺序并没有改变,如果不想在每次出队操作之后把所有元素移动一次,那就得利用已经出队的那个元素原来占有的位置,这样就出现循环队列
循环队列底层还是用数组实现,可以定义一个int类型的front变量和一个tail变量,分别用于记录队头元素所在的索引值和下一个入队的元素应该插入的位置的索引值.所以,循环队列为空的条件就是front==tail,由于是循环队列,所以表示相对位置的许多操作使用模运算实现
实现的时候还是先设计一个Queue接口类,用于定义一些队列所必须拥有的操作,再定义一个LoopQueue类实现这个接口
具体代码如下:
Queue接口类:
public interface Queue<E> {
public void enqueue(E e);
public E dequeue();
public E getFront();
public int getSize();
public boolean isEmpty();
}
LoopQueue循环队列类:
public class LoopQueue<E> implements Queue<E> {
private E[] data;
private int front,tail,size;
public LoopQueue(int capacity) {
data = (E[])new Object[capacity + 1];
front = 0;
tail = 0;
size = 0;
}
public LoopQueue() {
this(10);
}
@Override
public boolean isEmpty() {
return front == tail;
}
@Override
public int getSize() {
return this.size;
}
public int getCapacity() {
return this.data.length - 1;
}
@Override
public void enqueue(E e) {
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("队列为空");
}
E ret = data[front];
data[front] = null;
front = (front + 1) % data.length;
size --;
if( size == getCapacity() / 4 && getCapacity() / 2 != 0) {
reSize(getCapacity() / 2);
}
return ret;
}
@Override
public E getFront() {
if( isEmpty() ) {
throw new IllegalArgumentException("队列为空");
}
return data[front];
}
private void reSize(int capacity) {
E[] newData = (E[])new Object[capacity];
for(int i = 0; i < size; i++) {
newData[i] = data[(front + i ) % data.length];
}
data = newData;
front = 0;
tail = size;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("LoopQueue : size = "+getSize()+", capacity = "+getCapacity() +", length = "+ data.length + ", front [ ");
for(int i = front; i != tail ; i =(i + 1) % data.length) {
sb.append(data[i]);
if( (i + 1) % data.length != tail) {
sb.append(", ");
}
}
sb.append(" ] tail");
return sb.toString();
}
public static void main(String[] args) {
LoopQueue<Integer> queue = new LoopQueue<Integer>();
for(int i = 0; i < 15; i++) {
queue.enqueue(i);
System.out.println(queue);
}
queue.dequeue();
System.out.println(queue);
}
}