- 接口
public interface Queue<E> {
int getSize();
boolean isEmpty();
void enqueue(E e);
E dequeue();
E getFront();
}
- 队列-版本1
// [引用动态数组](https://www.jianshu.com/p/5c663b7c7282)
public class ArrayQueue<E> implements Queue<E> {
private Array<E> array;
public ArrayQueue() {
array = new Array<>();
}
public ArrayQueue(int capacity) {
array = new Array<>(capacity);
}
@Override
public int getSize() {
return array.getSize();
}
public int getCapacity() {
return array.getCapacity();
}
@Override
public boolean isEmpty() {
return array.isEmpty();
}
@Override
public void enqueue(E e) {
array.addLast(e);
}
@Override
public E dequeue() {
return array.removeFirst();
}
@Override
public E getFront() {
return array.getFirst();
}
@Override
public String toString() {
StringBuilder ret = new StringBuilder();
ret.append("Queue front[");
for (int i = 0; i < getSize(); i++) {
ret.append(array.get(i));
if (i != getSize() - 1) {
ret.append(",");
}
}
ret.append("] tail");
return ret.toString();
}
public static void main(String[] args) {
ArrayQueue<Integer> arrayQueue = new ArrayQueue<>();
for (int i = 0; i < 10; i++) {
arrayQueue.enqueue(i);
System.out.println(arrayQueue);
if (i % 3 == 2) {
arrayQueue.dequeue();
System.out.println(arrayQueue);
}
}
}
}
- 队列-版本2
//循环队列
public class LoopQueue<E> implements Queue<E> {
private E[] data;
private int front, tail;
private int size;
public LoopQueue() {
this(10);
}
public LoopQueue(int capacity) {
data = (E[]) new Object[capacity + 1];
front = 0;
tail = 0;
size = 0;
}
@Override
public int getSize() {
return size;
}
public int getCapacity() {
return data.length - 1;
}
@Override
public boolean isEmpty() {
return front == tail;
}
@Override
public void enqueue(E e) {
if ((tail + 1) % data.length == front) {
resize(getCapacity() * 2);
}
data[tail] = e;
tail = (tail + 1) % data.length;
size++;
}
@Override
public E dequeue() {
if (isEmpty()) {
throw new IllegalArgumentException("cannot dequeue a empty queue!");
}
E e = data[front];
front = (front + 1) % data.length;
size--;
if (size == getCapacity() / 4 && getCapacity() / 2 != 0) {
resize(getCapacity() / 2);
}
return e;
}
@Override
public E getFront() {
if (isEmpty()) {
throw new IllegalArgumentException("a empty queue!");
}
return data[front];
}
private void resize(int newCapacity) {
E[] newData = (E[]) new Object[newCapacity + 1];
for (int i = 0; i < size; i++) {
newData[i] = data[(front + i) % data.length];
}
data = newData;
front = 0;
tail = size;
}
@Override
public String toString() {
StringBuilder ret = new StringBuilder();
ret.append("Queue size:" + size + ", capacity:" + getCapacity() + "\n");
ret.append("front[");
for (int i = 0; i < size; i++) {
ret.append(data[(front + i) % data.length]);
if (i != size - 1) {
ret.append(",");
}
}
ret.append("] tail");
return ret.toString();
}
public static void main(String[] args) {
LoopQueue<Integer> arrayQueue = new LoopQueue<>();
for (int i = 0; i < 10; i++) {
arrayQueue.enqueue(i);
System.out.println(arrayQueue);
if (i % 3 == 2) {
arrayQueue.dequeue();
System.out.println(arrayQueue);
}
}
}
}
- 性能比较
版本1的dequeue时间复杂度为O(n)
public class Main {
public static double testQueue(Queue queue, int cnt) {
long start = System.nanoTime();
Random random = new Random();
for (int i = 0; i < cnt; i++) {
queue.enqueue(random.nextInt(Integer.MAX_VALUE));
}
for (int i = 0; i < cnt; i++) {
queue.dequeue();
}
long end = System.nanoTime();
return (end - start) / 1000000000.0;
}
public static void main(String[] args) {
final int cnt = 100000;
ArrayQueue<Integer> arrayQueue = new ArrayQueue<>();
System.out.println("arrayQueue:" + testQueue(arrayQueue, cnt));//arrayQueue:5.962328513
LoopQueue<Integer> loopQueue = new LoopQueue<>();
System.out.println("loopQueue:" + testQueue(loopQueue, cnt));//loopQueue:0.027345408
}
- JDK版本
public class ArrayDeque<E> extends AbstractCollection<E>
implements Deque<E>, Cloneable, Serializable
{
/**
* The array in which the elements of the deque are stored.
* The capacity of the deque is the length of this array, which is
* always a power of two. The array is never allowed to become
* full, except transiently within an addX method where it is
* resized (see doubleCapacity) immediately upon becoming full,
* thus avoiding head and tail wrapping around to equal each
* other. We also guarantee that all array cells not holding
* deque elements are always null.
*/
transient Object[] elements; // non-private to simplify nested class access
/**
* The index of the element at the head of the deque (which is the
* element that would be removed by remove() or pop()); or an
* arbitrary number equal to tail if the deque is empty.
*/
transient int head;
/**
* The index at which the next element would be added to the tail
* of the deque (via addLast(E), add(E), or push(E)).
*/
transient int tail;
/**
* The minimum capacity that we'll use for a newly created deque.
* Must be a power of 2.
*/
private static final int MIN_INITIAL_CAPACITY = 8;
...
网友评论