A queue is a collection of objects that are inserted and removed according to the first-in, first-out (FIFO) principle.
By convention, we assume that elements added to the queue can have arbitrary type and that a newly created queue is empty.
Queue Interface
public interface Queue<E> {
int size();
boolean isEmpty();
// Inserts an element at the rear of the queue
void enqueue(E e);
// Returns, but does not remove, the first element of the queue (null if empty)
E first();
// Removes and returns the first element of the queue (null if empty)
E dequeue();
}
Array-based Queue Implementation
/* Implementation of the queue ADT using a fixed-length array. */
public class ArrayQueue<E> implements Queue<E> {
private E[] data;
private int f = 0; // index of the front element
private int sz = 0; // current number of elements (size)
// constructors
public ArrayQueue() { this(CAPACITY); }
public ArrayQueue(int capacity) {
data = (E[]) new Object[capacity];
}
// methods
public int size() { return sz; }
public boolean isEmpty() { return (sz == 0); }
// insert an element at the rear of the queue
public void enqueue(E e) throws IllegalStateException {
if(sz == data.length) throw new IllegalStateException("Queue is full");
int avail = (f + sz) % data.length;
data[avail] = e;
sz++;
}
// returns, but does not remove, the first element of the queue (null if empty)
public E first() {
if(isEmpty()) return null;
return data[f];
}
// removes and returns the first element of the queue (null if empty)
public E dequeue() {
if(isEmpty()) return null;
E answer = data[f];
data[f] = null; // deference to help garbage collection
f = (f + 1) % data.length;
sz--;
return answer;
}
}
enqueue(E e)分析
public void enqueue(E e) throws IllegalStateException {
if(sz == data.length) throw new IllegalStateException("Queue is full");
int avail = (f + sz) % data.length;
data[avail] = e;
sz++;
}
新元素能插入的前提是Queue还没有装满,也就是说sz < data.length
。
假设f = 11, sz = 10, data.length = 20
现在我们要在这个Queue的末尾插入一个新元素E e
。
avail = (11 + 10) % 20 // 1
data[1] = e;
sz++; // 11
dequeue()分析
public E dequeue() {
if(isEmpty()) return null;
E answer = data[f];
data[f] = null; // deference to help garbage collection
f = (f + 1) % data.length;
sz--;
return answer;
}
f
的范围就是[0, data.length-1]
这种实现方法的好处是,dequeue
的操作,在移除Queue
第一个元素之后,不需要通过一个for loop
把后面的元素全部向前挪动一位,因为使用for loop
会降低dequeue
操作的效率。
Implementing A Queue with A Singly Linked List
public class LinkedQueue<E> implements Queue<E> {
private SinglyLinkedList<E> list = new SinglyLinkedList<>(); // an empty list
public LinkedQueue() {} // new queue relies on the initially empty list
public int size() { return list.size(); }
public boolean isEmpty() { return list.isEmpty(); }
public void enqueue(E element) { list.addLast(element); }
public E first() { return list.first(); }
public E dequeue() {return list.removeFirst(); }
}
A Circular Queue
待补充