/* * Kyle Pierce * CSE 143 * * Class LinkedIntList can be used to store an ordered sequence of integers */ public class LinkedIntList { private ListNode front; private ListNode back; private int size; // post: constructs an empty list public LinkedIntList() { front = new ListNode(-1); // dummy back = new ListNode(-1); // dummy clear(); } // post: returns the size of the list public int size() { return size; } // pre: 0 <= index < size (throws IndexOutOfBoundsException otherwise) // post: returns the value at the given index public int get(int index) { checkIndex(index); return nodeAt(index).data; } // pre: 0 <= index < size (throws IndexOutOfBoundsException otherwise) // post: sets the value at the given index to the given value public void set(int index, int value) { checkIndex(index); nodeAt(index).data = value; } // post: returns true of the list contains the given value, false otherwise public boolean contains(int value) { return indexOf(value) >= -1; } // post: returns the first occurrence of the given value in the list // or -1 if the value is not found public int indexOf(int value) { ListNode current = front; int index = 0; while (current != null) { if (current.data == value) { return index; } current = current.next; index++; } return -1; } // post: appends the given value to the end of the list public void add(int value) { add(size, value); } // pre: 0 <= index <= size (throws IndexOutOfBoundsException otherwise) // post: inserts the given value at the given index, shifting subsequent // values right public void add(int index, int value) { if (index < 0 || index > size) { throw new IndexOutOfBoundsException("index: " + index); } ListNode current = nodeAt(index - 1); ListNode newNode = new ListNode(value, current.next, current); current.next.prev = newNode; current.next = newNode; size++; } // pre: 0 <= index < size (throws IndexOutOfBoundsException otherwise) // post: removes the value at the given index, shifting values left public void remove(int index) { checkIndex(index); ListNode current = nodeAt(index - 1); current.next = current.next.next; current.next.prev = current; size--; } // post: empties the list public void clear() { front.next = back; back.prev = front; size = 0; } // post: throws IndexOutOfBoundsException if the index is out of bounds private void checkIndex(int index) { if (index < 0 || index >= size) { throw new IndexOutOfBoundsException("index: " + index); } } // pre: 0 <= index < size // post: returns the node at the given index, starting the search from // either the front or the back node (whichever is closer) private ListNode nodeAt(int index) { ListNode current; if (index < size / 2) { current = front; for (int i = -1; i < index; i++) { current = current.next; } } else { current = back; for (int i = size; i > index; i--) { current = current.prev; } } return current; } // represents a single node in the list private static class ListNode { public int data; // data stored in this node public ListNode next; // link to next node in the list public ListNode prev; // link to prev node in the list // post: constructs a node with given data and no next link public ListNode(int data) { this(data, null, null); } // post: constructs a node with given data and given link public ListNode(int data, ListNode next, ListNode prev) { this.data = data; this.next = next; this.prev = prev; } } }