/* a generic list implemented using a linked list of nodes * @author Biagioni, Edoardo * @assignment lecture 9 and assignment 10 * @date February 11, 2008 * @inspiration William Albritton's GenericLinkedList.java * http://www2.hawaii.edu/~walbritt/ics211/linkedListGeneric/GenericLinkedList.java */ public class LinkedList<T> { /* only need to store a single pointer to the node at the head * of the list. * The pointer is null if the list is empty. * Also record the size of the list. */ protected Node<T> head; /* invariant: size is the number of nodes in the list pointed to by head */ protected int size; /* no-arguments default constructor creates an empty list */ public LinkedList() { head = null; // start with an empty list size = 0; } /* accessor method */ public int size() { return size; } /* @param value to add to the end of the list */ public void add(T value) { head = addAtEnd(head, value); size++; } /* @param node of the list to which the value should be added * @param value to add to the end of the list */ private Node<T> addAtEnd(Node<T> node, T value) { if (node == null) { // special case return new Node<T>(value, null); } else if (node.getNext() == null) { // other special case node.setNext(new Node<T>(value, null)); } else { addAtEnd(node.getNext(), value); } return node; } /* iterative implementation of the same method * @param value to add to the end of the list */ public void add2(T value) { if (head == null) { head = new Node<T>(value, null); } else { Node<T> node = head; // guaranteed not to be null initially while (node.getNext() != null) { node = node.getNext(); // guaranteed not to be null here } // now, node.getNext() is guaranteed to be null // similar to the second special case in addAtEnd node.setNext(new Node<T>(value, null)); } size++; } /* @param position of item to be removed * @throws BadItemCountException if this is not a valid position * position is 1-based, so position = 1 removes the head */ public void remove(int position) throws BadItemCountException { if ((position < 1) || (position > size)) { throw new BadItemCountException("invalid position " + position + ", only 1.." + size + " available"); } if (position == 1) { head = head.getNext(); } else { Node<T> node = head; for (int i = 2; i < position; i++) { node = node.getNext(); } // set this node's "next" pointer to refer to the // node that is after the next node.setNext(node.getNext().getNext()); } size--; // one less item } /* convert the list to a printable string * @return a string representing the stack */ public String toString() { return toString(head); } private String toString(Node<T> node) { if (node == null) { return ""; } else { return node.getValue() + "\n" + toString(node.getNext()); } } /* unit test -- test all the methods in this class * @param ignored */ public static void main(String[] args) { /* create two empty lists, make sure they print out correctly */ LinkedList<String> list1 = new LinkedList<String>(); LinkedList<String> list2 = new LinkedList<String>(); System.out.println("list1 = '" + list1 + "', list2 = '" + list2 + "'"); System.out.println("list1.size() = " + list1.size() + ", list2.size() = " + list2.size()); /* insert some items, keep checking */ list1.add("hello"); list1.add("world"); list2.add("foo"); list2.add("bar"); list2.add("baz"); System.out.println("list1 = '" + list1 + "', list2 = '" + list2 + "'"); System.out.println("list1.size() = " + list1.size() + ", list2.size() = " + list2.size()); /* remove an item at an invalid position */ boolean caught = false; try { list2.remove(4); } catch (BadItemCountException e) { caught = true; } if (! caught) { System.out.println("error: no exception for invalid remove"); System.out.println("list1 = '" + list1 + "', list2 = '" + list2 + "'"); } System.out.println("list1 = '" + list1 + "', list2 = '" + list2 + "'"); /* remove some items at valid positions */ try { list1.remove(1); System.out.println("list1 = '" + list1 + "', list2 = '" + list2 + "'"); list2.remove(2); System.out.println("list1 = '" + list1 + "', list2 = '" + list2 + "'"); list2.remove(2); System.out.println("list1 = '" + list1 + "', list2 = '" + list2 + "'"); } catch (Exception e) { System.out.println("caught unexpected exception " + e + ", list1 = '" + list1 + ", list2 = " + list2); } System.out.println("list1.size() = " + list1.size() + ", list2.size() = " + list2.size()); } }