import java.util.NoSuchElementException; /** * Single-linked list implementation of an ordered lists of objects. * Initial version translated fairly naively from BasicArrayList
* CSE 373 demonstration program, Winter 2006 * @author Hal Perkins * @version 1/8/06 */ public class BasicLinkedList implements BasicList { // Representation of a single link in the list. // Class members and variables are public for easy access inside // BasicLinkedList. Class is private so that Links can't be directly // accessed outside. private class Link { public Object item; // list element referenced by this link public Link next; // next link or null if this is the last // link in the list // constructor for convenience public Link(Object item, Link next) { this.item = item; this.next = next; } } // list state private Link head; // reference to first link in the list, or // null if the list is empty // constructor /** * Construct a new empty BasicLinkedList */ public BasicLinkedList() { head = null; } // queries /* return number of elements in this list. specified in interface BasicList */ public int size() { // count the number of links in the list int nItems = 0; Link p = head; while (p != null) { nItems++; p = p.next; } return nItems; } /* return true if this list is empty. specified in interface BasicList */ public boolean isEmpty() { return size() == 0; } /* return true if obj is in this list. specified in interface BasicList */ public boolean contains(Object obj) { return indexOf(obj) != -1; } /* return location of given item or -1. specified in interface BasicList */ public int indexOf(Object obj) { // sequential search int pos = 0; // position of current link in the list Link p = head; while (p != null) { if (p.item.equals(obj)) { return pos; } p = p.next; pos++; } return -1; } // internal methods to check arguments // throw IndexOutOfBoundsException if pos is out of range private void checkIndex(int pos) { if (pos < 0 || pos >= size()) { throw new IndexOutOfBoundsException("Invalid BasicArrayList index"); } } // throw IllegalArgumentException if obj is null private void checkArgument(Object obj) { if (obj == null) { throw new IllegalArgumentException("Attempt to add null to BasicArrayList"); } } // internal method to access link by position // return link at position pos in this list // precondition: 0 <= pos < size(). // Will fail if position is invalide, including when list is empty. private Link getLinkAtPos(int pos) { int k = 0; Link result = head; while (k < pos) { k++; result = result.next; } return result; } // set/get methods /* get item at given position. specified in interface BasicList */ public Object get(int pos) throws IndexOutOfBoundsException { checkIndex(pos); return getLinkAtPos(pos).item; } /* set item at given position. specified in interface BasicList */ public Object set(int pos, Object obj) throws IllegalArgumentException, IndexOutOfBoundsException { checkIndex(pos); checkArgument(obj); Link p = getLinkAtPos(pos); Object result = p.item; p.item = obj; return result; } // basic list manipulation /* remove everything from this list. specified in interface BasicList */ public void clear() { // null out items to avoid unneeded references to objects Link p = head; while (p != null) { p.item = null; p = p.next; } // set list to empty head = null; } /* add item at end of list. specified in interface BasicList */ public boolean add(Object item) throws IllegalArgumentException { if (isEmpty()) { addFirst(item); } else { Link last = getLinkAtPos(size()-1); last.next = new Link(item, null); } return true; } /* add item at beginning of list. specified in interface BasicList */ public void addFirst(Object item) throws IllegalArgumentException { head = new Link(item, head); } /* add item at given position. specified in interface BasicList */ public void add(int pos, Object item) throws IllegalArgumentException, IndexOutOfBoundsException { checkIndex(pos); checkArgument(item); // special case: if adding at position 0, this is the new first // link; otherwise, insert after pos-1. if (pos == 0) { addFirst(item); } else { Link prev = getLinkAtPos(pos-1); Link newLink = new Link(item, prev.next); prev.next = newLink; } } /* remove first copy of obj from this list. specified in interface BasicList */ public boolean remove(Object obj) { int pos = indexOf(obj); if (pos != -1) { remove(pos); return true; } else { return false; } } /* return and remove element from this list. specified in interface BasicList */ public Object remove(int pos) throws IndexOutOfBoundsException { checkIndex(pos); Object result; // If pos is 0, remove first link, otherwise remove internal link if (pos == 0) { result = head.item; head = head.next; } else { Link prev = getLinkAtPos(pos-1); result = prev.next.item; prev.next = prev.next.next; } return result; } /* remove and return first element in list. specified in interface BasicList */ public Object removeFirst() throws NoSuchElementException { if (isEmpty()) { throw new NoSuchElementException("Trying to remove first item from empty list"); } return remove(0); } /* remove and return last element in list. specified in interface BasicList */ public Object removeLast() throws NoSuchElementException { if (isEmpty()) { throw new NoSuchElementException("Trying to remove last item from empty list"); } return remove(size()-1); } // printable representation /** * Return a string representation of this BasicArrayList * @return the elements in the list separated by commas and surrounded by [] */ public String toString() { String result = "["; if (size() > 0) { result = result + get(0); } for (int i = 1; i < size(); i++) { result = result + "," + get(i); } return result + "]"; } // iteration /* return an iterator for this list. specified in interface BasicList */ public BasicListIterator iterator() { return new BasicLinkedListIterator(); } // Iterator class for BasicArrayList private class BasicLinkedListIterator implements BasicListIterator { private Link nextLink; // position of next link to be returned by this iteration // construct new iterator initialized to return the first item public BasicLinkedListIterator() { nextLink = head; } /* return true if more items. specified in BasicListIterator */ public boolean hasNext() { return nextLink != null; } /* return next item. specified in BasicListIterator */ public Object next() throws NoSuchElementException { if (!hasNext()) { throw new NoSuchElementException(); } Object result = nextLink.item; nextLink = nextLink.next; return result; } // unimplemented iterator functions /* specified in BasicListIterator */ public boolean hasPrevious() { throw new UnsupportedOperationException("not implemented"); } /* specified in BasicListIterator */ public Object previous() throws NoSuchElementException { throw new UnsupportedOperationException("not implemented"); } /* specified in BasicListIterator */ public void remove() throws IllegalStateException { throw new UnsupportedOperationException("not implemented"); } } }