循环队列
循环队列就是将队列存储空间的最后一个位置绕到第一个位置,形成逻辑上的环状空间,供队列循环使用。在循环队列结构中,当存储空间的最后一个位置已被使用而再要进入队运算时,只需要存储空间的第一个位置空闲,便可将元素加入到第一个位置,即将存储空间的第一个位置作为队尾。 [1] 循环队列可以更简单防止伪溢出的发生,但队列大小是固定的。
Queue接口的定义
public interface Queue<E> {
public int getSize();
public boolean isEmpty();
public void clear();
/**
* 入队一个元素e
* @param e
*/
public void enqueue(E e);
/**
* 出队一个元素e
* @return
*/
public E dequeue();
/**
* 获取队头
* @return
*/
public E getFront();
/**
* 获取队尾
* @return
*/
public E getRear();
}
ArrayQueueLoop类对Queue接口的实现
public class ArrayQueueLoop<E> implements Queue<E>{
private E[] data; //定义一个数组
private int front; //定义一个头指针
private int rear; //定义一个尾指针
private int size; //定义一个有效容量大小
private static int DEFAULT_SIZE = 10; //默认容量
public ArrayQueueLoop() {
this(DEFAULT_SIZE);
}
public ArrayQueueLoop(int capacity) {
data = (E[]) new Object[capacity + 1];
front = 0;
rear = 0;
size = 0;
}
//获取元素个数
@Override
public int getSize() {
return size;
}
//判断队列是否为空
@Override
public boolean isEmpty() {
return front == rear && size == 0;
}
//清空队列
@Override
public void clear() {
size = 0;
front = 0;
rear = 0;
//E[] data = (E[]) new Object[DEFAULT_SIZE];
}
//元素进队操作
@Override
public void enqueue(E e) {
//判断是否满了扩容
if((rear + 1) % data.length == front) {
resize(data.length* 2 - 1); //容量满了则扩大二倍
}
data[rear] = e;
rear = (rear + 1) % data.length;
size++;
}
//更改队列容量
private void resize(int newLen) {
E[] newData = (E[]) new Object[newLen]; //创建一个新的数组
int index = 0; //新数组的角标
for(int i = front; i != rear;i = (i + 1) % data.length) { //将数据复制到新数组
newData[index++] = data[i];
}
front = 0;
rear = index;
data = newData;
}
//出队操作
@Override
public E dequeue() {
if(isEmpty()) {
throw new NullPointerException("队列为空");
}
E e = data[front];
front = (front + 1) % data.length;
size--;
if(size <= data.length / 4 && data.length > DEFAULT_SIZE) {
resize(data.length/2 + 1);
}
return e;
}
//获得队头元素
@Override
public E getFront() {
return data[front];
}
//获取队尾元素
@Override
public E getRear() {
return data[(data.length + rear - 1) % data.length];
}
//重写了toString方法
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ArrayQueueLoop: size =" + getSize() + ",capacity=" + (data.length - 1) + "\n");
if(isEmpty()) {
sb.append("[]");
}else {
sb.append('[');
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();
}
}