We add two protected instance data
members
first
and
last
. Both are of type
int
.
The data member size
is eliminated.
The new class together with a sample test program is given below.
The asymptotic complexity of each method is the same as that
for the corresponding method of
ArrayLinearList
.
public class ArrayCircularList implements LinearList { // data members protected Object [] element; // array of elements protected int first; // location of first element protected int last; // location of last element // constructors /** create a list with initial capacity initialCapacity * @throws IllegalArgumentException when * initialCapacity < 1 */ public ArrayCircularList(int initialCapacity) { if (initialCapacity < 1) throw new IllegalArgumentException ("initialCapacity must be >= 1"); // size has the default initial value of 0 element = new Object [initialCapacity]; first = -1; // list is empty } /** create a list with initial capacity 10 */ public ArrayCircularList() {// use default capacity of 10 this(10); } // methods /** @return true iff list is empty */ public boolean isEmpty() {return first == -1;} /** @return current number of elements in list */ public int size() { if (first == -1) return 0; else return (element.length + last - first) % element.length + 1; } /** @throws IndexOutOfBoundsException when * index is not between 0 and size - 1 */ void checkIndex(int index) { if (index < 0 || index >= size()) throw new IndexOutOfBoundsException ("index = " + index + " size = " + size()); } /** @return element with specified index * @throws IndexOutOfBoundsException when * index is not between 0 and size - 1 */ public Object get(int index) { checkIndex(index); return element[(first + index) % element.length]; } /** @return index of first occurrence of elem, * return -1 if theElement not in list */ public int indexOf(Object theElement) { // search element[] for theElement int size = size(); for (int i = 0; i < size; i++) if (element[(first + i) % element.length].equals(theElement)) return i; // elem not found return -1; } /** Remove the element with specified index. * All elements with higher index have their * index reduced by 1. * @throws IndexOutOfBoundsException when * index is not between 0 and size - 1 * @return removed element */ public Object remove(int index) { Object elementToReturn = get(index); // no exception thrown, valid index, remove element if (size() == 1) {// list becomes empty element[first] = null; // enable garbage collection first = -1; return elementToReturn; } // determine which side has fewer elements // and shift the smaller number of elements int size = size(); if (index <= (size - 1) / 2) {// shift elements index - 1 ... 0 for (int i = index - 1; i >= 0; i--) element[(first + i + 1) % element.length] = element[(first + i) % element.length]; element[first] = null; // enable gc first = (first + 1) % element.length; } else {// shift elements index + 1 ... size() - 1 for (int i = index + 1; i < size(); i++) element[(first + i - 1) % element.length] = element[(first + i) % element.length]; element[last] = null; // enable gc last = (element.length + last - 1) % element.length; } return elementToReturn; } /** Insert an element with specified index. * All elements with equal or higher index * have their index increased by 1. * @throws InexOutOfBoundsException when * index is not between 0 and size */ public void add(int index, Object theElement) { if (index < 0 || index > size()) // invalid list position throw new IndexOutOfBoundsException ("index = " + index + " size = " + size()); // valid index, handle empty list as special case if (first == -1) {// insert into empty list first = last = 0; element[0] = theElement; return; } // insert into a nonempty list, make sure we have space if (size() == element.length) {// no space, double capacity // allocate a new array Object [] newArray = new Object [2 * element.length]; // copy elements into new array int j = 0; // position in newArray to copy to for (int i = first; i != last; i = (i + 1) % element.length) newArray[j++] = element[i]; newArray[j] = element[last]; // copy last element // switch to newArray and set first and last element = newArray; first = 0; last = j; } // create space for new element if (index <= size() / 2) {// shift elements 0 through index - 1 for (int i = 0; i < index; i++) element[(element.length + first + i - 1) % element.length] = element[(first + i) % element.length]; first = (element.length + first - 1) % element.length; } else {// shift elements size() - 1 ... index for (int i = size() - 1; i >= index; i--) element[(first + i + 1) % element.length] = element[(first + i) % element.length]; last = (last + 1) % element.length; } // insert new element element[(first + index) % element.length] = theElement; } /** convert to a string */ public String toString() { int size = size(); StringBuffer s = new StringBuffer("["); if (size != 0) {// nonempty list // do first element s.append(element[first % element.length].toString()); for (int i = 1; i < size; i++) s.append(", " + element[(first + i) % element.length].toString()); } s.append("]"); // create equivalent String return new String(s); } }
System.arraycopy
to copy and/or shift segments of
array elements rather than do this one element as a time as is done above.
ArrayCircularList.*
.