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}