/** * A list implemented using a singly-linked list and using recursive methods * @author Edo Biagioni * @lecture ICS 211 Jan 27 (or later) * @date January 26, 2011 */ public class LinkedListRec<E> { // here, include the LinkedNode definition /** * A node in a singly-linked list * @author Edo Biagioni * @lecture ICS 211 Jan 27 or later * @date January 26, 2010 */ private static class LinkedNode<T> { private T item; private LinkedNode<T> next; /** * constructor to build a node with no successor * @param the value to be stored by this node */ private LinkedNode(T value) { item = value; next = null; } /** * constructor to build a node with specified (maybe null) successor * @param the value to be stored by this node * @param the next field for this node */ private LinkedNode(T value, LinkedNode<T> reference) { item = value; next = reference; } } // end of the LinkedNode definition // this is the start of the linked list. If the list is empty, it is null protected LinkedNode<E> head; /** * initializes an empty linked list */ public LinkedListRec() { head = null; } /** recursive private method, called by the public wrapper method * @param the head of the list (may be null if we are at the end) * @return the size of the list */ private int size(LinkedNode<E> current) { if (current == null) { return 0; // an empty list has size 0 } // a non-empty list has size 1 more than the rest of the list: return 1 + size (current.next); } /** public wrapper method, calls the private recursive method public int size() { return size(head); } /** recursive private method, called by the public wrapper method * @param the head of the list (may be null if we are at the end) * @param the value to be added * @return the list, with the value added */ private LinkedNode<E> addAtEnd(LinkedNode<E> node, E value) { if (node == null) { return new LinkedNode<E>(value); } node.next = addAtEnd(node.next, value); return node; } /** public wrapper method, calls the private recursive method * @param the value to be added at the end of the linked list */ public void add(E value) { head = addAtEnd(head, value); } /** recursive private method, called by the public wrapper method * @param the head of the list (may be null if we are at the end) * @param the number of nodes to skip before inserting * @param the value to be added * @return the list, with the value added */ private LinkedNode<E> addAtPosition(LinkedNode<E> node, int skip, E value) { if (skip == 0) { return new LinkedNode<E>(value, node); } if (node == null) { // node is null but skip > 0 -- bad index throw new IndexOutOfBoundsException("bad index for add"); } node.next = addAtPosition(node.next, skip - 1, value); return node; } /** public wrapper method, calls the private recursive method * @param the position at which to add: 0 to add at the start * @param the value to be added * @throws IndexOutOfBoundsException if the index is less than 0 * or greater than the number of elements in the linked list */ public void add(int index, E value) { head = addAtPosition(head, index, value); } /** recursive private method, called by the public wrapper method * @param the head of the list (may be null if we are at the end) * @param the value to be removed * @return the list, with the value removed */ private LinkedNode<E> remove(LinkedNode<E> node, E value) { if (node == null) { // node is null but skip > 0 -- bad index return node; } if (node.item.equals(value)) { return node.next; // match, so remove this node } node.next = remove(node.next, value); return node; } /** public wrapper method, calls the private recursive method * @param the object to remove */ public void remove(E value) { head = remove(head, value); } /** recursive private method, called by the public wrapper method * @param the head of the list (may be null if we are at the end) * @return the string representing the list */ private String toString(LinkedNode<E> node) { if (node == null) { return ""; } if (node.next == null) { return node.item.toString(); } return node.item.toString() + " ==> " + toString(node.next); } /** * concatenates the elements of the linked list, separated by " ==> " * @return the string representation of the list */ public String toString() { return toString(head); } /** * unit test method -- basic testing of the functionality * @param required, ignored */ public static void main (String [] arguments) { LinkedListRec<String> ll = new LinkedListRec<String>(); System.out.println (ll); ll.add("foo"); System.out.println (ll); ll.add(1, "bar"); System.out.println (ll); ll.add("baz"); System.out.println (ll); ll.add(0, "hello"); System.out.println (ll); ll.add(1, "world"); System.out.println (ll); ll.remove ("foo"); // remove an intermediate element System.out.println (ll); ll.remove ("hello"); // remove the first element System.out.println (ll); ll.remove ("baz"); // remove the last element System.out.println (ll); } }