1、循环队列
我们上次基于动态数组实现的队列,出队是 O(n) 级别的,非常的 low,这里我用另外一种思路来实现队列
我们使用两个变量 front 和 tail,分别代表数组第一个元素的索引和最后一个元素的后一个索引
使用 data[front] 出队,data[tail] 入队
队列为空:size == 0
队列为满:size == length
public class LoopQueue<E> implements Queue<E> {
private E[] data;
private int front;
private int tail;
private int size;
public LoopQueue2(int capacity) {
data = (E[]) new Object[capacity];
front = tail = size = 0;
}
public LoopQueue2() {
this(10);
}
@Override
public void enqueue(E e) {
if (size == data.length) resize(data.length * 2);
data[tail] = e;
tail = (tail + 1) % data.length;
size++;
}
@Override
public E dequeue() {
if (isEmpty()) throw new RuntimeException("队列为空");
E ret = data[front];
data[front] = null;
front = (front + 1) % data.length;
size--;
if (size == data.length / 4 && data.length / 2 != 0) resize(data.length / 2);
return ret;
}
@Override
public E getFront() {
if (isEmpty()) throw new RuntimeException("队列为空");
return data[front];
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
public int getCapacity() {
return data.length;
}
/**
* 动态数组
*/
private void resize(int newCapacity) {
E[] newData = (E[]) new Object[newCapacity];
for (int i = 0; i < size; i++) {
newData[i] = data[(i + front) % data.length];
}
data = newData;
front = 0;
tail = size;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(String.format("LoopQueue2: size = %d, capacity = %d\n", size, getCapacity()));
sb.append("Front [");
for (int i = 0; i < size; i++) {
sb.append(data[(i + front) % data.length]);
if (i != size - 1) sb.append(", ");
}
sb.append("] Tail");
return sb.toString();
}
}
2、双端队列
有了循环队列队列的基础,双端队列也可以非常容易的实现
public class Deque<E> {
private E[] data;
private int front;
private int tail;
private int size;
public Deque(int capacity) {
data = (E[]) new Object[capacity];
front = tail = size = 0;
}
public Deque() {
this(10);
}
public void addFront(E e) {
if (size == data.length) resize(data.length * 2);
front = (front != 0) ? (front - 1) : (data.length - 1);
data[front] = e;
size++;
}
public void addLast(E e) {
if (size == data.length) resize(data.length * 2);
data[tail] = e;
tail = (tail + 1) % data.length;
size++;
}
public E removeFront() {
if (isEmpty()) throw new RuntimeException("队列为空");
E ret = data[front];
data[front] = null;
front = (front + 1) % data.length;
size--;
if (size == data.length / 4 && data.length / 2 != 0) resize(data.length / 2);
return ret;
}
public E removeLast() {
if (isEmpty()) throw new RuntimeException("队列为空");
tail = (tail != 0) ? (tail - 1) : (data.length - 1);
E ret = data[tail];
data[tail] = null;
size--;
if (size == data.length / 4 && data.length / 2 != 0) resize(data.length / 2);
return ret;
}
public E getFront() {
if (isEmpty()) throw new RuntimeException("队列为空");
return data[front];
}
public E getLast() {
if (isEmpty()) throw new RuntimeException("队列为空");
return (tail != 0) ? data[tail - 1] : data[data.length - 1];
}
public boolean isEmpty() {
return size == 0;
}
public int getSize() {
return size;
}
public int getCapacity() {
return data.length;
}
private void resize(int newCapacity) {
E[] newData = (E[]) new Object[newCapacity];
for (int i = 0; i < size; i++) {
newData[i] = data[(i + front) % data.length];
}
data = newData;
front = 0;
tail = size;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(String.format("Deque: size = %d, capacity = %d\n", getSize(), getCapacity()));
sb.append('[');
for (int i = 0; i < getSize(); i++) {
sb.append(data[(i + front) % data.length]);
if (i != getSize() - 1) sb.append(", ");
}
sb.append(']');
return sb.toString();
}
}
标签:队列,tail,length,循环,front,data,public,size
From: https://www.cnblogs.com/n139949/p/17302826.html