We can use simple array to store items as a queue.
backfront index.Leads to problems:
back may reach last array index,front reaches last array index, cannot enqueue anymore.Solutions:
front and back.or
What happens when front or back reach maxSize?
Indexing an element beyond the end of the array.
Instead, must do
front = (front + 1) % maxSize; back = (back + 1) % maxSize;
But what if the array fills up?
Easy, make a new, bigger array.
But what if current queue spans across last and first array element?
front and into new array starting at beginning of new arrayfront in usual way (front+1) % maxQueueSizefront to 0back to size - 1maxQueueSize to new array sizeStudy the following code. First, the interface.
public interface QueueInterface<T> { public boolean isEmpty(); public void enqueue(T newItem); public T dequeue() throws QueueException; public T peek() throws QueueException; }
Now here is an exception we can use.
public class QueueException extends java.lang.RuntimeException { public QueueException(String s) { super(s); } }
Now, the actual queue implementation. This java file includes a main function to test it.
Using a generic type for the elements of the array causes problems. We cannot do
T [] items = new T[20];
Java compiler needs to know how much storage space to allocate. So, instead we can do
T [] items = (T[]) new Object[20];
The java compiler will warn you about doing this, saying
Note: Queue.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details.
and if you compile with the recommended argument, you see
warning: [unchecked] unchecked cast
at that line in the source code, among other things.
public class Queue<T> implements QueueInterface<T> { protected int maxQueueSize; protected T [] items; protected int front; protected int back; protected int size; public Queue(int maxSize) { maxQueueSize = maxSize; items = (T[]) new Object[maxQueueSize]; //because cannot do new T[n] front = 0; back = maxQueueSize-1; size = 0; } public boolean isEmpty() { return size == 0; } public boolean isFull() { return size == maxQueueSize; } public void enqueue(T newItem) { if (isFull()) { // Resize the array int newSize = maxQueueSize * 2; T [] newItems = (T[]) new Object[newSize]; // Copy items from old array at i to new array at k int i = front; for (int k = 0; k < size; k++) { newItems[k] = items[i]; i = (i + 1) % maxQueueSize; } // Assign array variable, front and back indices, and maxQueueSize items = newItems; front = 0; back = size - 1; maxQueueSize = newSize; } // Assign newItem to element at back, after incrementing back back = (back + 1) % maxQueueSize; items[back] = newItem; ++size; } public T dequeue() throws QueueException { if (!isEmpty()) { T queueFront = items[front]; front = (front + 1) % maxQueueSize; --size; return queueFront; } else { throw new QueueException("Queue: Attempt to dequeue an empty queue."); } } public T peek() throws QueueException { if (!isEmpty()) { return items[front]; } else { throw new QueueException("Queue: Attempt to peek an empty queue."); } } public String toString() { String result = "Q: "; for (int i = front; i <= back; i = (i+1) % maxQueueSize) { result += items[i] + " "; } return result; } public String toStringDebug() { String result = " Q debug: "; String fbmarkers = " "; for (int i = 0; i < maxQueueSize; i++) { T item = items[i]; String itemString; if (item == null) { itemString = "_ "; } else { itemString = item.toString() + " "; } String fb = ""; result += itemString; if (i == front) { int n = itemString.length() - 1; fb += "f"; } if (i == back) { fb += "b"; } int nBlanks = itemString.length() - fb.length(); fb += (nBlanks <= 0)? "" : String.format("%" + nBlanks + "s", ""); // adding n blanks fbmarkers += fb; } return result + "\n" + fbmarkers; } public static void main(String [] args) { Queue<String> q = new Queue<String>(4); q.enqueue("a"); System.out.println("\t\t\t\tenqueue(\"a\")"); System.out.println(q.toStringDebug()); q.enqueue("b"); System.out.println("\t\t\t\tenqueue(\"b\")"); System.out.println(q.toStringDebug()); System.out.println("\n" + q + "\n"); String removed = q.dequeue(); System.out.println("\t\t\t\tdequeue() = \"" + removed + "\""); System.out.println(q.toStringDebug()); System.out.println("\n" + q + "\n"); } }
Compile Queue.java and then run it. You should see
> java Queue
enqueue("a")
Q debug: a _ _ _
fb
enqueue("b")
Q debug: a b _ _
f b
Q: a b
dequeue() = "a"
Q debug: a b _ _
fb
Q: b
The toStringDebug method shows the queue contents
as the full array with f and b underneath marking the values
of the indices front and back.
Study the enqueue method and make sure you understand how it works.
Now add some code to main to further test this queue by adding more items and removing items. Test whether or not it correctly resizes the array.
Rather than doing a lot of copying and pasting, write a couple of
simple methods to add an item, remove an item, and print the queue. With properly
defined static methods, you should be able to replace the body of
the main function with code like
add(q,"a");
remove(q);
that does the enqueue and dequeue and prints the information
as done by the example code in main.
You should soon see a problem in the output. Figure out what the problem is and fix it.
When you have done the above steps, including fixing the bug, show the instructor that your code works. This is necessary to get your grade for this recitation.
If you did not have time to show the instructor your working code, then you may submit it via RamCT, under “Recit Week 2”.
The bug is obvious if you do these operations:
Queue<String> q = new Queue<String>(4); add(q,"a"); add(q,"b"); add(q,"c"); add(q,"d"); remove(q); add(q,"e"); System.out.println("\n" + q + "\n");
You should see
enqueue("a")
Q debug: a _ _ _
fb
enqueue("b")
Q debug: a b _ _
f b
enqueue("c")
Q debug: a b c _
f b
Q: a b c
enqueue("d")
Q debug: a b c d
f b
dequeue() = "a"
Q debug: a b c d
f b
enqueue("e")
Q debug: e b c d
b f
Q:
The last call to Queue.toString() didn't work! So, you must fix the
implementation of Queue.toString(), so that this example works. Then,
submit your Queue.java to the “Recit Week 2 Missed” assignment.