不想讲解,直接上代码.需要学习的直接看注释.
/**
* @author Relic
* @desc 动态循环数组实现队列
* @date 2019-12-10 16:53
*/
public class DynamicArrayQueue<E> {
private static final int DEFAULT_SIZE = 16;
/**
* 队首索引
*/
private int front;
/**
* 队尾索引
*/
private int rear;
/**
* 实现当前队列数组的实际容量
*/
private int capacity;
/**
* 实际数据
*/
private Object[] data;
public DynamicArrayQueue() {
this(DEFAULT_SIZE);
}
/**
* 将队首队尾都标识为 -1 表示队列的初始化
*
* @param capacity 给定初始容量,将实际存储数据的数组初始化
*/
public DynamicArrayQueue(int capacity) {
front = -1;
rear = -1;
this.capacity = capacity;
data = new Object[capacity];
}
/**
* 判断队列是否已经满了
*
* @return 队列是否已满
*/
public boolean isFull() {
//这里先队尾 +1 再对容量取余可以取到当 rear 已经达到最大容量时的实际位置
return (rear + 1) % capacity == front;
}
/**
* 判断队列是否已经空了
*
* @return 队列是否已空
*/
public boolean isEmpty() {
return front == -1;
}
/**
* 获取当前队列的长度
*
* @return 当前队列中元素的个数
*/
public int size() {
if (front == -1) {
return 0;
}
//如果刚好满了,取余之后会得到 0,所以要判断下 size (这里加上一个容量是因为 rear - front 可能是 负的)
int size = (rear - front + 1 + capacity) % capacity;
return size == 0 ? capacity : size;
}
/**
* 数组扩容
*/
private void resize() {
//扩容到两倍
capacity = capacity * 2;
Object[] oldData = data;
data = new Object[capacity];
// 将源数据复制到新的数组中
System.arraycopy(oldData, 0, data, 0, oldData.length);
/*
当队尾小于队首时,说明队尾的索引已经到了队首的前面
所以要将从 0 到队尾的元素移动到原数组最大容量位置之后
将新数组原位置置为 null 垃圾回收
*/
if (rear < front) {
int initCapacity = capacity / 2;
for (int i = 0; i < rear; i++) {
data[initCapacity + i] = oldData[i];
data[i] = null;
}
rear = rear + initCapacity;
}
}
/**
* 入队操作
*/
public void enQueue(E element) {
//判断队列是否已满,如果已经满了则需要进行扩容
if (isFull()) {
resize();
}
//确定当前队尾的索引值,因为是循环数组,环可能已经超出 capacity 的大小
rear = (rear + 1) % capacity;
data[rear] = element;
//当队首还处于初始化状态时,将队首置为 0 (进这个逻辑时 rear 只能是 0)
if (front == -1) {
front = rear;
}
}
/**
* 出队一个元素
*
* @return 队首的元素
*/
@SuppressWarnings("unchecked")
public E deQueue() {
//如果栈空了,抛出异常
if (isEmpty()) {
throw new RuntimeException("队列已空");
}
E current = (E) data[front];
//当队首已经到了队尾的时候, 说明队列已空, 将队列返回初始化状态
if (front == rear) {
front = rear = -1;
} else {
front = (front + 1) % capacity;
}
return current;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < size(); i++) {
if (i != 0) {
sb.append(",");
}
sb.append(data[(front + i) % capacity].toString());
}
sb.append("]");
return sb.toString();
}
}
测试类
import org.junit.Test;
public class DynamicArrayQueueTest {
@Test
public void queue() {
DynamicArrayQueue<Integer> queue = new DynamicArrayQueue<>();
queue.enQueue(2);
queue.enQueue(5);
queue.enQueue(4);
queue.enQueue(3);
queue.enQueue(1);
queue.deQueue();
queue.deQueue();
System.out.println(queue);
System.out.println(queue.size());
System.out.println(queue.isEmpty());
}
}
result: