import java.util.Iterator;
// ARRAY QUEUE. A fixed length queue implemented as a circular array.
class ArrayQueue {
private int front; // Index of front object in BASES.
private int rear; // Index of rear object in BASES.
private Base[] bases; // The BASEs in the queue.
// Constructor. Make a new empty queue that can hold SIZE - 1 elements.
public ArrayQueue(int size) {
if (size >= 1) {
front = 0;
rear = 0;
bases = (Base[]) new Object[size];
} else {
throw new IllegalArgumentException("Size must be at least 1.");
}
}
// DEQUEUE. Remove a BASE from the front of the queue and return it.
public Base dequeue() {
if (isEmpty()) {
throw new IllegalStateException("Queue is empty.");
} else {
front = (front + 1) % bases.length;
Base temp = bases[front];
bases[front] = null;
return temp;
}
}
// ENQUEUE. Add BASE to the rear of the queue.
public void enqueue(Base base) {
int nextRear = (rear + 1) % bases.length;
if (front == nextRear) {
throw new IllegalStateException("Queue is full.");
} else {
rear = nextRear;
bases[rear] = base;
}
}
// IS EMPTY. Test if the queue is empty.
public boolean isEmpty() {
return front == rear;
}
// IS FULL. Test if the queue can hold no more elements.
public boolean isFull() {
return front == (rear + 1) % bases.length;
}
private class ArrayQueueIterator implements Iterator {
private int where;
private ArrayQueueIterator() {
where = (front + 1) % bases.length;
}
public boolean hasNext() {
return where != (rear + 1 ) % bases.length;
}
public Base next() {
if (hasNext()){
Base temp = bases[where];
where = (where + 1) % bases.length;
return temp;
} else {
throw new IllegalStateException("Queue is at its end.");
}
}
public void remove() {
//Do nothing
}
}
public Iterator iterator() {
return new ArrayQueueIterator();
}
}
// QUEUETERATOR. Test ARRAY QUEUE's iterator. It's worth 20 points.
class Queueterator {
// MAIN. Start execution here.
public static void main(String[] args) {
// Make an ARRAY QUEUE and enqueue some STRINGs. It can hold at most three.
ArrayQueue queue = new ArrayQueue(4);
queue.enqueue("A");
queue.enqueue("B");
queue.enqueue("C");
// Make a FIRST iterator for QUEUE and use it to visit QUEUE's elements.
Iterator first = queue.iterator();
while (first.hasNext()) {
System.out.println(first.next()); // A B C one per line 5 pts.
}
// Make sure FIRST hasn't changed QUEUE.
System.out.println(queue.isEmpty()); // false 1 pt.
System.out.println(queue.dequeue()); // A 1 pt.
System.out.println(queue.dequeue()); // B 1 pt.
System.out.println(queue.dequeue()); // C 1 pt.
System.out.println(queue.isEmpty()); // true 1 pt.
// Let's enqueue more three more things to QUEUE.
queue.enqueue("X");
queue.enqueue("Y");
queue.enqueue("Z");
// Now make a SECOND iterator for QUEUE. The FIRST one does not work any more,
// because QUEUE has changed. Use SECOND to visit QUEUE's new elements.
Iterator second = queue.iterator();
while (second.hasNext()) {
System.out.println(second.next()); // X Y Z one per line 5 pts.
}
// The new iterator hasn't changed QUEUE either.
System.out.println(queue.isEmpty()); // false 1 pt.
System.out.println(queue.dequeue()); // X 1 pt.
System.out.println(queue.dequeue()); // Y 1 pt.
System.out.println(queue.dequeue()); // Z 1 pt.
System.out.println(queue.isEmpty()); // true 1 pt.
}
}