/**
* @Classname MyDeque
* @Description 使用循环数组实现双端队列
* @Date 2022-7-8 19:14
* @Created by Yang Yi-zhou
*/
public class MyDeque<E> {
//默认容量
private static final int DEFAULT_CAPACITY = 8;
//最大容量
private static final int MAX_CAPACITY = Integer.MAX_VALUE;
//存储数组
private Object[] elements;
//队列头
private int head;
//队列尾
private int tail;
//队列元素个数
private int size;
//无参构造器,使用默认容量初始化
public MyDeque() {
//初始化
this.elements = new Object[DEFAULT_CAPACITY];
this.head = 0;
this.tail = 0;
this.size = 0;
}
//指定容量大小的构造器
public MyDeque(int capacity) {
//合法性检查
if (capacity < 0 || capacity > MAX_CAPACITY) {
throw new IllegalArgumentException("parameter is illegal");
}
//使用给定的容量初始化
this.elements = new Object[capacity];
this.head = 0;
this.tail = 0;
this.size = 0;
}
/**
* 在双端队列的开头添加指定的元素。
*
* @param element 要添加的元素
* @return 是否添加成功
*/
public boolean offerFirst(E element) {
//判断队列是否满了
if (size == elements.length) {
doubleCapacity();
}
//如果队列为空
if (isEmpty()) {
elements[head] = element;
} else {
//添加元素到队列头,head左移
elements[getRealIndex(head - 1)] = element;
//更新队列状态
head = getRealIndex(head - 1);
}
size++;
return true;
}
/**
* 在双端队列的尾部添加指定的元素。
*
* @param element 要添加的元素
* @return 是否添加成功
*/
public boolean offerLast(E element) {
//判断队列是否满了
if (size == elements.length) {
doubleCapacity();
}
//如果队列为空
if (isEmpty()) {
elements[tail] = element;
} else {
//添加元素到队列尾,tail右移
elements[getRealIndex(tail + 1)] = element;
//更新队列状态
tail = getRealIndex(tail + 1);
}
size++;
return true;
}
/**
* 返回并删除双端队列的队头元素。如果双端队列为空,则返回null。
*
* @return
*/
public E pollFirst() {
//判断队列是否为空
if (isEmpty()) return null;
//删除除队列的第一个元素
E removedElement = (E) elements[head];
elements[head] = null;
//head右移
head = getRealIndex(head + 1);
size--;
return removedElement;
}
/**
* 返回并删除双端队列的队尾元素。如果双端队列为空,则返回null。
*
* @return
*/
public E pollLast() {
//判断队列是否为空
if (isEmpty()) return null;
//删除除队列的第一个元素
E removedElement = (E) elements[tail];
elements[tail] = null;
//tail左移
tail = getRealIndex(tail - 1);
size--;
return removedElement;
}
/**
* 返回双端队列的第一个元素。如果双端队列为空,则返回null。
*
* @return
*/
public E peekFirst() {
if (isEmpty()) return null;
return (E) elements[head];
}
/**
* 返回双端队列的最后一个元素。如果双端队列为空,则返回null。
*
* @return
*/
public E peekLast() {
if (isEmpty()) return null;
return (E) elements[tail];
}
/**
* 判断队列是否为空
*
* @return true:为空 false:不为空
*/
public boolean isEmpty() {
return size == 0;
}
/**
* 扩增队列容量
*/
public void doubleCapacity() {
//检查队列是否已达到上限
if (elements.length == MAX_CAPACITY) throw new RuntimeException("deque is full");
//新的队列容量为目前的两倍
int newCapacity = elements.length * 2;
//检查新容量是否超过最大容量限制
if (newCapacity > MAX_CAPACITY) newCapacity = MAX_CAPACITY;
//使用新容量构造一个新的数组
Object[] newArr = new Object[newCapacity];
//把元素移动到新的数组中
for (int i = 0; i < elements.length; i++) {
newArr[i] = elements[getRealIndex(head + i)];
}
//更新队列状态
head = 0;
tail = elements.length - 1;
elements = newArr;
}
/**
* 获取真实下标
*
* @param logicIndex 逻辑下标
* @return 真实下标
*/
private int getRealIndex(int logicIndex) {
int innerArrayLength = elements.length;
//逻辑下标小于0
if (logicIndex < 0) {
//加上当前数组的长度
logicIndex += innerArrayLength;
}
//逻辑下标大于等于数组长度
if (logicIndex >= innerArrayLength) {
//减去当前数组的长度
logicIndex -= innerArrayLength;
}
//返回真实下标
return logicIndex;
}
/**
* 打印deque
*/
public void printDeque() {
for (int i = 0; i < elements.length; i++) {
if (elements[getRealIndex(head + i)] == null) break;
System.out.print(elements[getRealIndex(head + i)].toString());
System.out.print("-->");
}
System.out.println("\b\b\b");
}
}
Java实现双端队列
最新推荐文章于 2024-07-25 19:54:12 发布