循环队列的实现
循环队列的定义
该循环队列的实现思想也是动态数组,但是由于操作元素的特殊性,并不能直接由ArrayList或ArrayQueue实现,所以从头开始定义ArrayLoopQueue
图解循环队列的操作
循环队列的扩容缩容图解
ArrayLoopQueue类代码实现
public class ArrayLoopQueue<E> implements Queue<E> {
//存储元素的容器
private E[] data;
//队首指针front
private int front;
//队尾指针rear
private int rear; //front == rear 队列空;(rear + 1)%data.length == front 队列满
//有效元素的个数size
private int size;
private static int DEFAULT_SIZE = 10;
public ArrayLoopQueue(){
this(DEFAULT_SIZE);
}
//capacity 容量 存储元素的最大容量 10 -> 9可用的 1不可用的
public ArrayLoopQueue(int capacity){
data = (E[]) new Object[capacity + 1];
front = 0;
rear = 0;
size = 0;
}
//获取循环队列的有效元素个数
@Override
public int size() {
return size;
}
//判断循环队列是否为空
@Override
public boolean isEmpty() {
return size == 0 && front == rear;
}
//向循环队列入队一个元素
@Override
public void offer(E element) {
//判断是否需要扩容
if ((rear + 1) % data.length == front){
resize(data.length * 2 - 1);
}
data[rear] = element;
rear = (rear + 1) % data.length;
size++;
}
//向循环队列出队一个元素
@Override
public E poll() {
if (isEmpty()){
throw new NullPointerException("queue is null");
}
E ret = data[front];
front = (front + 1) % data.length;
size--;
//判断是否缩容
if (size == (data.length - 1) / 4 && data.length - 1 > DEFAULT_SIZE){
resize(data.length / 2 + 1);
}
return ret;
}
private void resize(int newLength) {
E[] newData =(E[]) new Object[newLength];
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 element() {
if (isEmpty()){
throw new NullPointerException("queue is null");
}
return data[front];
}
@Override
public void clear() {
data = (E[]) new Object[DEFAULT_SIZE + 1];
front = 0;
rear = 0;
size = 0;
}
public boolean equals(Object o){
if (o == null){
return false;
}if (this == o){
return true;
}if ( o instanceof ArrayLoopQueue){
ArrayLoopQueue<E> other = (ArrayLoopQueue<E>) o;
if (size != other.size){
return false;
}
int i = front;
int j = other.front;
while (i != rear){
if (!data[i].equals(other.data[j])){
return false;
}
i = (i + 1) % data.length;
j = (j + 1) % other.data.length;
}
return true;
}
return false;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(String.format("ArrayLoopQueue:%d/%d[",size,data.length - 1));
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 ArrayLoopQueueIterator();
}
class ArrayLoopQueueIterator implements Iterator<E>{
private int cur = front;
@Override
public boolean hasNext() {
return cur != rear;
}
@Override
public E next() {
E ret = data[cur];
cur = (cur + 1) % data.length;
return ret;
}
}