200 likes | 208 Views
Example: LinkedSet<T>. LinkedSet<T> Class LinkedSet Attributes/Constructor Linked Set Methods LinkedSet iterator method LinkedIterator<T> class Reading: L&C 3 rd : 15.4 2 nd : 4.1-4.5. 1. LinkedSet<T> Class.
E N D
Example: LinkedSet<T> • LinkedSet<T> Class • LinkedSet Attributes/Constructor • Linked Set Methods • LinkedSet iterator method • LinkedIterator<T> class • Reading: L&C 3rd: 15.4 2nd: 4.1-4.5 1
LinkedSet<T> Class • The LinkedSet<T> class implements the same SetADT<T> interface as ArraySet<T> using a singly linked list instead of an array • Externally, your code is not much different when using the LinkedSet<T> class instead of the ArraySet<T> class: SetADT<String> mySet = new ArraySet<String>(); OR = new LinkedSet<String>(); • Internally, method code of the LinkedSet<T> class is very different due to the difference in the underlying data structure being used. 2
LinkedSet<T> Class • Again: We assume that SetADT<T> interface extends Iterable. 3
LinkedSet Attributes/Constructor • The class definition starts with: public class LinkedSet<T> implements SetADT<T> { private static Random rand = new Random(); private int count; private LinearNode<T> contents; public LinkedSet() // default constructor { count = 0; contents = null; // NOTE: not an array } 4
LinkedSet Attributes/Constructor • We don’t need to define a default capacity or pass an initial capacity to the constructor • We don’t need to instantiate an array object or any LinearNode objects in the constructor – just set contents to null 5
LinkedSet Methods • Note that because we are not using a fixed size data structure such as an array, we don’t need a private expandCapacity() method. 6
LinkedSet Methods • add – O(n) public void add (T element) { if (!contains(element)) { LinearNode<T> node = new LinearNode<T>(element); node.setNext(contents); contents = node; count++; } } 7
LinkedSet Methods • contains – O(n) public boolean contains (T target) { LinearNode<T> next = contents; while (next != null) { if (next.getElement().equals(target) return true; next = next.getNext(); } return false; } 8
LinkedSet Methods • removeRandom – O(n) not O(1) like ArraySet public T removeRandom() throws EmptySetException { LinearNode<T> current; T result = null; if (isEmpty) throw new EmptySetException(); int choice = rand.nextInt(count) + 1; 9
LinkedSet Methods • removeRandom (Continued) if (choice == 1) { // remove from beginning result = contents.getElement(); contents = contents.getNext(); } else { // remove from middle or end current = contents; for (int skip = 2; skip < choice; skip++) current = current.getNext(); result = current.getNext().getElement(); current.setNext(current.getNext().getNext()); } count--; return result; } // bypassed LinearNode becomes garbage 10
LinkedSet iterator Method • iterator – O(1) public Iterator<T> iterator { return new LinkedIterator<T>(contents) } • We will study the LinkedIterator class to understand how it is implemented 11
LinkedIterator<T> Class • We may have several collection classes like the LinkedSet class that use an underlying singly linked linear data structure • Again, we would like to reuse one Iterator class for all of these collection classes • So we write a general purpose Iterator class for use with linked data structures 12
LinkedIterator<T> Class • The iterator method of the LinkedSet class instantiates and returns a reference to a LinkedIterator object to its caller • The LinkedIterator constructor needs to get a reference to the first LinearNode object in the specific linked structure to be iterated 13
LinkedIterator<T> Class • Class / Attribute Definitions and Constructor public class LinkedIterator<T> implements Iterator<T> { private LinearNode<T> current; // current position public LinkedIterator(LinearNode<T> current) { this.current = current; } 14
LinkedIterator Methods • hasNext – O(1) public boolean hasNext() { return current != null; } • next – O(1) public T next() { if (!hasNext()) throw new NoSuchElementException(); T result = current.getElement(); current = current.getNext(); return result; } // old LinearNode does not become garbage (Why?) 15
LinkedIterator 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(); } 16
LinkedIterator Methods • Again, if we 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 17
LinkedIterator Method Analysis • All three LinkedIterator 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) 18
LinkedIterator Class in Text • There is an anomaly in the definition of the LinkedIterator class in the textbook • The class has a count attribute and the constructor has a parameter to set count • But that attribute is not used anywhere in the code of the other methods • The code can and does always identify the end of the list by the null terminator value • Why was count included? 19
LinkedSet Alternative • If the count attribute was of no use in the LinkedIterator class, is it also of no use in the LinkedSet class? • It is possible to implement the code of the LinkedSet class without a count attribute • What is adversely affected by removing it? • Size method would become O(n) instead of O(1) • RemoveRandom method would need to use size method to calculate its choice of node to remove, but it is already O(n) 20