ArraySet Methods and ArrayIterator • Homework review • ArraySet and ArrayIterator Methods with Big-O analysis • Reading: L&C 3rd ed:15.3, Pages 40-41 2nd ed: 3.6. (Book has some mistakes.) 1 Problem size parameter • In analyzing the time complexity of the operations of the ArraySet class we need to choose the parameters which specifies the size of our problem. • We choose the size of the set: n to be the parameter. Then, we analyze the time complexity of ArraySet with respect to changes in the size of the set. • In Big-O analysis we always consider the worst case. ArrayIterator Methods • Default constructor should NOT be used • May want to include this code to prevent any calls to the default constructor: private ArrayIterator() { } • Overloaded Constructor: public ArrayIterator(T[] collection, int count) { items = collection; // NOTE: creates an alias // not a new array this.count = count; current = 0; } 3 ArrayIterator Methods • hasNext – O(1) public boolean hasNext() { return current < count; } • next – O(1) public T next() { if (!hasNext()) throw new NoSuchElementException(); return items[current++]; } 4 ArrayIterator Methods • remove – O(1) • We don’t need to implement real code for the remove method, but there is no return value that we can use to indicate that it is not implemented • If we don’t implement it, we indicate that the code is not implemented by throwing an exception public void remove() throws UnsupportedOperationException { throw new UnsupportedOperationException(); } 5 ArrayIterator Methods • If we do implement the remove method, notice that we don’t specify the element that is to be removed and we do not return a reference to the element being removed • It is assumed that the calling code has been iterating on condition hasNext() and calling next() and already has a reference • The last element returned by next() is the element that will be removed 6 ArrayIterator Method Analysis • All three ArrayIterator methods are O(1) • However, they are usually called inside an external while loop or “for-each” loop • Hence, the process of “iterating” through a collection using an Iterator is O(n) 7 ArraySet Methods • size - O(1) public int size() { return count; } • isEmpty – O(1) public boolean isEmpty() { return count == 0; } ArraySet Methods • expandCapacity – O(n) private void expandCapacity() { T[] larger = (T[]) new Object[2 * contents.length]; for (int i = 0; i < contents.length; i++) larger[i] = contents[i]; contents = larger; // original array // becomes garbage } ArraySet Methods • contains – O(n): The code is a bit different than the one used in the book (both O(n)). public boolean contains(T target) { for (T element : contents) if (target.equals(element)) return true; return false; } ArraySet Methods • add – O(n) public void add (T element) { if (!contains(element)) { if (size() == contents.length) expandCapacity(); contents[count] = element; count++; } } ArraySet Methods • addAll – O( (2n + m).m) • (Note: We also can code addAll using a foreach loop because we added extends Iterable to SetADT interface definition) public void addAll(setADT<T> set) { for(T element : set) add(element); } ArraySet Methods • remove – O(n) public T remove(T target) throws EmptySetException, NoSuchElementException { if (isEmpty()) throw new EmptySetException(); for (int i = 0; i < count; i++) { if (contents[i].equals(target)) { T result = contents[i]; contents[i] = contents[--count]; contents[count] = null; return result; } } throw new NoSuchElementException(); } ArraySet Methods • removeRandom – O(1) public T removeRandom() throws EmptySetException { if (isEmpty()) throw new EmptySetException(); int choice = rand.nextInt(count); T result = contents[choice]; contents[choice] = contents[count-1]; contents[count-1] = null; count--; return result; } ArraySet Methods • removeRandom (Bad Alternative?) • We may want to avoid some duplicate code in the removeRandom method and make it shorter. • Throws any EmptySetException that occurs in remove public T removeRandom() throws EmptySetException { return remove(contents[rand.nextInt(count)]); } The above alternative algorithm is O(n) instead of O(1)! ArraySet Methods • union: • this set size: n parameter set size m public SetADT<T> union (SetADT<T> set) { ArraySet<T> both = new ArraySet<T>(); both.addAll(this);//O((0+n).n)=O(n.n) both.addAll(set); //O((2n+m).m) return both; } O(n.n) + O((2n+m).m) = O(n.n + 2m.n + m.m) 16 ArraySet Methods • toString – O(n) public String toString() { String result = “”; for (T obj : contents) { if (obj == null) // first null is at count return result; result += obj + “\n”; } return result; // exactly full – no nulls } 17 ArraySet Methods • iterator – O(1) public Iterator<T> iterator() { return new ArrayIterator<T>(contents, count); } 18