import java.util.*; /** * Linkedlist127 -- a singly linked list developed in class by CS127 * on 16 and 18 January 2006. * * David Liben-Nowell (skeleton only) * Carleton College Winter 2006 CS 127 class (everything else). * */ class LinkedList127 { /** * The nested Node class -- it's static to prevent us from doing * anything stupid, like fiddling with LinkedList instance variables. */ private static class Node { public E data; // the value stored in this node. public Node successor; // the node after this one in the list, // or null if this node is the last. } private Node head; // the first node in the list, or null if the // list is empty. private Node tail; // the last node in the list, or null if empty. private int size; // the number of elements in the list. /** * Constructor -- creates an empty list. */ public LinkedList127() { head = null; size = 0; tail = null; } /** * Returns a string version of the list. */ public String toString() { String str = ""; Node current = head; while (current != null) { str = str + " -> [" + current.data + "]"; current = current.successor; } return str; } /** * Returns the (index)th node in the list. */ private Node getNode(int index) throws IndexOutOfBoundsException { if (index < 0 || index >= this.size() ) { throw new IndexOutOfBoundsException(); } Node current = head; int counter = 0; while (counter < index) { current = current.successor; counter++; } return current; } /** * Returns the value stored in the (index)th node in the list. */ public E get(int index) { return getNode(index).data; } /** * Adds a new node with value x at the beginning of list. */ public void prepend(E x) { Node newNode = new Node(); newNode.data = x; newNode.successor = head; head = newNode; size++; if (size == 1) { // we just added the only node in the list tail = head; } } /** * Adds a new node with value x at the end of list. */ public void append(E x) { if (head == null) { prepend(x); } else { // current.successor is null, so current is the last node in list. Node newNode = new Node(); newNode.data = x; newNode.successor = null; tail.successor = newNode; tail = newNode; size++; } } /** * Returns the number of nodes in the list. */ public int size() { return size; } /** * Deletes the (index)th node in the list. */ public void delete(int index) { if (index == 0) { head = head.successor; size--; if (size == 0) { // list is now empty tail = null; } } else if (index >= this.size()) { throw new IndexOutOfBoundsException(); } else { Node previousNode = getNode(index-1); if (index == size-1) { // we're deleting the old tail tail = previousNode; } previousNode.successor = previousNode.successor.successor; size--; } } /** * The nested Iterator class -- it's NOT static because we need * access to "head". */ private class LLIterator implements Iterator { Node current; // the "bookmark" of the iterator. // constructor -- bookmark initially begins at the head of the list. public LLIterator() { current = head; } // hasNext -- there's a next element to report unless we're at the end. public boolean hasNext() { return (current != null); } // next -- return the next element to report, and advance current. public E next() { E elmt = current.data; current = current.successor; return elmt; } // remove -- would delete the just-reported element if // written. (Note that this requires some changes in the // above, because in this implementation you can't access the // element you just reported, because current has already // moved on.) public void remove() { throw new UnsupportedOperationException("remove not implemented"); } } // == "give me a new iterator for this list." public LLIterator iterator() { return new LLIterator(); } }