
/**
 * Class that implements a backward queue using a singly-linked list
 *   @author Dave Reed
 *   @version 9/2/17
 */
public class BackwardQueue<E> {
    private Node<E> front;
    private Node<E> back;
    private int numNodes;
    
    /**
     * Constructs an empty queue.
     */
    public BackwardQueue() {
        this.front = null;
        this.back = null;
        this.numNodes = 0;
    }
    
    /**
     * Determines whether the queue is empty.
     *   @return true if no items currently stored in the queue 
     */
    public boolean empty() {
        return (this.size() == 0);
    }
    
    /**
     * Determines the size of the queue.
     *   @return the number of items currently stored in the queue
     */
    public int size() {
        return this.numNodes;
    }
    
    /**
     * Adds a new data value at the front of the queue.
     *   @param value the value to be added
     */
    public void add(E value) {
        this.front = new Node<E>(value, this.front);
        if (this.front.getNext() == null) {
            this.back = this.front;
        }
        this.numNodes++;
    }
    
    /**
     * Removes a value from the back of the queue.
     *   @return the item previously at the front
     *   @throws java.util.EmptyStackException 
     */
    public E remove() throws java.util.NoSuchElementException {
        if (this.empty()) {
            throw(new java.util.NoSuchElementException());
        }
        else {
            E backData;
            
            if (this.size() == 1) {
                backData = this.front.getData();
                this.front = null;
                this.back = null;
            }
            else {
                Node<E> stepper = this.front;
                while (stepper.getNext() != null) {
                    stepper = stepper.getNext();
                }
                backData = stepper.getNext().getData();
                stepper.setNext(null);
                this.back = stepper;
            }
            this.numNodes--;
            return backData;
        }
    }
    
    /**
     * Peeks at the value currently at the back of the queue.
     *   @return the item at the front
     *   @throws java.util.NoSuchElementException 
     */
    public E peek() throws java.util.NoSuchElementException {
        if (this.empty()) {
            throw(new java.util.NoSuchElementException());
        }
        else {
            return this.back.getData();           
        }
    }
    
    /////////////////////////////////////////////////////////////
    
    public static void main(String[] args) {
        BackwardQueue<Integer> nums = new BackwardQueue<Integer>();
        for (int i = 1; i <= 10; i++) {
            nums.add(i);
        }
        
        while (!nums.empty()) {
            System.out.println(nums.remove());
        }
    }
}

