001package algs13; 002import stdlib.*; 003import java.util.Iterator; 004import java.util.NoSuchElementException; 005/* *********************************************************************** 006 * Compilation: javac Queue.java 007 * Execution: java Queue < input.txt 008 * Data files: http://algs4.cs.princeton.edu/13stacks/tobe.txt 009 * 010 * A generic queue, implemented using a linked list. 011 * 012 * % java Queue < tobe.txt 013 * to be or not to be (2 left on queue) 014 * 015 *************************************************************************/ 016/** 017 * The {@code Queue} class represents a first-in-first-out (FIFO) 018 * queue of generic items. 019 * It supports the usual <em>enqueue</em> and <em>dequeue</em> 020 * operations, along with methods for peeking at the top item, 021 * testing if the queue is empty, and iterating through 022 * the items in FIFO order. 023 * <p> 024 * All queue operations except iteration are constant time. 025 * <p> 026 * For additional documentation, see <a href="http://algs4.cs.princeton.edu/13stacks">Section 1.3</a> of 027 * <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne. 028 */ 029public class Queue<T> implements Iterable<T> { 030 private int N; // number of elements on queue 031 private Node<T> first; // beginning of queue 032 private Node<T> last; // end of queue 033 034 // helper linked list class 035 private static class Node<T> { 036 public Node() { } 037 public T item; 038 public Node<T> next; 039 } 040 041 /** 042 * Create an empty queue. 043 */ 044 public Queue() { 045 first = null; 046 last = null; 047 N = 0; 048 } 049 050 /** 051 * Is the queue empty? 052 */ 053 public boolean isEmpty() { 054 return first == null; 055 } 056 057 /** 058 * Return the number of items in the queue. 059 */ 060 public int size() { 061 return N; 062 } 063 064 /** 065 * Return the item least recently added to the queue. 066 * @throws java.util.NoSuchElementException if queue is empty. 067 */ 068 public T peek() { 069 if (isEmpty()) throw new NoSuchElementException("Queue underflow"); 070 return first.item; 071 } 072 073 /** 074 * Add the item to the queue. 075 */ 076 public void enqueue(T item) { 077 Node<T> oldlast = last; 078 last = new Node<>(); 079 last.item = item; 080 last.next = null; 081 if (isEmpty()) first = last; 082 else oldlast.next = last; 083 N++; 084 } 085 086 /** 087 * Remove and return the item on the queue least recently added. 088 * @throws java.util.NoSuchElementException if queue is empty. 089 */ 090 public T dequeue() { 091 if (isEmpty()) throw new NoSuchElementException("Queue underflow"); 092 T item = first.item; 093 first = first.next; 094 N--; 095 if (isEmpty()) last = null; 096 return item; 097 } 098 099 /** 100 * Return string representation. 101 */ 102 public String toString() { 103 StringBuilder s = new StringBuilder(); 104 for (T item : this) 105 s.append(item + " "); 106 return s.toString(); 107 } 108 109 // check internal invariants 110 private static <T> boolean check(Queue<T> that) { 111 int N = that.N; 112 Queue.Node<T> first = that.first; 113 Queue.Node<T> last = that.last; 114 if (N == 0) { 115 if (first != null) return false; 116 if (last != null) return false; 117 } 118 else if (N == 1) { 119 if (first == null || last == null) return false; 120 if (first != last) return false; 121 if (first.next != null) return false; 122 } 123 else { 124 if (first == last) return false; 125 if (first.next == null) return false; 126 if (last.next != null) return false; 127 128 // check internal consistency of instance variable N 129 int numberOfNodes = 0; 130 for (Queue.Node<T> x = first; x != null; x = x.next) { 131 numberOfNodes++; 132 } 133 if (numberOfNodes != N) return false; 134 135 // check internal consistency of instance variable last 136 Queue.Node<T> lastNode = first; 137 while (lastNode.next != null) { 138 lastNode = lastNode.next; 139 } 140 if (last != lastNode) return false; 141 } 142 143 return true; 144 } 145 146 147 /** 148 * Return an iterator that iterates over the items on the queue in FIFO order. 149 */ 150 public Iterator<T> iterator() { 151 return new ListIterator(); 152 } 153 154 // an iterator, doesn't implement remove() since it's optional 155 private class ListIterator implements Iterator<T> { 156 private Node<T> current = first; 157 158 public boolean hasNext() { return current != null; } 159 public void remove() { throw new UnsupportedOperationException(); } 160 161 public T next() { 162 if (!hasNext()) throw new NoSuchElementException(); 163 T item = current.item; 164 current = current.next; 165 return item; 166 } 167 } 168 169 public void toGraphviz(String filename) { 170 GraphvizBuilder gb = new GraphvizBuilder (); 171 toGraphviz (gb, null, first); 172 gb.toFile (filename, "rankdir=\"LR\""); 173 } 174 private void toGraphviz (GraphvizBuilder gb, Node<T> prev, Node<T> n) { 175 if (n == null) { gb.addNullEdge (prev); return; } 176 gb.addLabeledNode (n, n.item.toString ()); 177 if (prev != null) gb.addEdge (prev, n); 178 toGraphviz (gb, n, n.next); 179 } 180 181 /** 182 * A test client. 183 */ 184 public static void main(String[] args) { 185 Trace.drawStepsOfMethod("main"); 186 Trace.drawStepsOfMethod("enqueue"); 187 Trace.drawStepsOfMethod("dequeue"); 188 Trace.run(); 189 StdIn.fromString ("to be or not to - be - - that - - - is"); 190 Queue<String> q = new Queue<>(); 191 int count = 0; 192 //q.toGraphviz ("queue" + count + ".png"); count++; 193 while (!StdIn.isEmpty()) { 194 String item = StdIn.readString(); 195 if (!item.equals("-")) q.enqueue(item); 196 else if (!q.isEmpty()) StdOut.print(q.dequeue() + " "); 197 //q.toGraphviz ("queue" + count + ".png"); count++; 198 } 199 StdOut.println("(" + q.size() + " left on queue)"); 200 } 201}