/**
 * Class that implements a stack using a singly-linked list
 *   @author Dave Reed
 *   @version 10/1/17
 */
public class LinkedStack<E> {
    private Node<E> top;
    private int numNodes;
    
    /**
     * Constructs an empty stack.
     */
    public LinkedStack() {
        this.top = null;
        this.numNodes = 0;
    }
    
    /**
     * Determines whether the stack is empty.
     *   @return true if no items currently stored in the stack 
     */
    public boolean empty() {
        return (this.size() == 0);
    }
    
    /**
     * Determines the size of the stack.
     *   @return the number of items currently stored in the stack
     */
    public int size() {
        return this.numNodes;
    }
    
    /**
     * Pushes a new data value onto the top of the stack.
     *   @param value the value to be pushed
     */
    public void push(E value) {
        this.top = new Node<E>(value, this.top);
        this.numNodes++;
    }
    
    /**
     * Pops a value off of the top of the stack.
     *   @return the item previously on top
     *   @throws java.util.NoSuchElementException 
     */
    public E pop() throws java.util.NoSuchElementException {
        if (this.empty()) {
            throw(new java.util.NoSuchElementException());
        }
        else {
            E topData = this.top.getData();
            this.top = this.top.getNext();
            this.numNodes--;
            return topData;
        }
    }
    
    /**
     * Peeks at the value currently on top of the stack.
     *   @return the item on top
     *   @throws java.util.NoSuchElementException 
     */
    public E peek() throws java.util.NoSuchElementException {
        if (this.empty()) {
            throw(new java.util.NoSuchElementException());
        }
        else {
            return this.top.getData();           
        }
    }
    
    /////////////////////////////////////////////////////////////
    
    public static void main(String[] args) {
        LinkedStack<Integer> nums = new LinkedStack<Integer>();
        for (int i = 1; i <= 10; i++) {
            nums.push(i);
        }
        
        while (!nums.empty()) {
            System.out.println(nums.pop());
        }
    }
}
