/**
 * A liniked list implementation of a list of elements.
 * 
 * @author Paul Chew
 * 
 * Created September 2005.
 */
public class LinkedList implements List {
    
    ListCell head;      // Head (first cell) of the List
    
    /**
     * Constructor.
     */
    public LinkedList () {
        head = null;
    }
            
    /**
     * Insert an element onto the list.
     * @param element the element to insert
     */
    public void insert (Object element) {
        head = new ListCell(element, head);
    }
    
    /**
     * Delete an element from the list.
     * @param element the element to delete
     */
    public void delete (Object element) {
        head = delete(element, head);
    }
    
    private static ListCell delete (Object element, ListCell cell) {
        if (cell == null) return null;
        if (cell.datum.equals(element)) return cell.next;
        cell.next = delete(element, cell.next);
        return cell;
    }
    
    /**
     * Report true if list contains element.
     * @param element the element to check for
     * @return true iff element is in the List
     */
    public boolean contains (Object element) {
        return contains(element, head);
    }
    
    private static boolean contains (Object element, ListCell cell) {
        if (cell == null) return false;
        if (cell.datum.equals(element)) return true;
        return contains(element, cell.next);
    }
    
    /**
     * Report number of elements in List.
     * @return number of elements
     */
    public int size () {
        return size (head);
    }
    
    private static int size (ListCell cell) {
        if (cell == null) return 0;
        return 1 + size(cell.next);
    }
    
    /**
     * String representation.
     * @return the String representation
     */
    public String toString () {
        return "[" + toString(head) + " ]";
    }
    
    private static String toString (ListCell cell) {
        if (cell == null) return "";
        return " " + cell.datum.toString() + toString(cell.next);
    }
}

/**
 * List cell.
 */
class ListCell {
    
    public Object datum;     // Data for this cell
    public ListCell next;    // Next cell
    
    /**
     * Constructor.
     */
    public ListCell (Object datum, ListCell next) {
        this.datum = datum;
        this.next = next;
    }
}
