Example: LinkedSet, iterator Method, and LinkedIterator Class

advertisement
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()
{
count = 0;
contents = null;
}
// default constructor
// 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;
15
} // old LinearNode does not become garbage (Why?)
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,
20
but it is already O(n)
Download