ordered containers cmput 115 - lecture 19 department of computing science university of alberta...
TRANSCRIPT
Ordered ContainersOrdered Containers
CMPUT 115 - Lecture 19
Department of Computing Science
University of Alberta
©Duane Szafron 2003Some code in this lecture is based on code from the book:
Java Structures by Duane A. Bailey or the companion structure package
©Duane Szafron 2003
2
About This LectureAbout This Lecture
In this lecture we will learn about Ordered containers.
An ordered container is a container where the order of the elements depends not on the order they are added, but rather on comparisons of the elements that are added.
©Duane Szafron 2003
3
OutlineOutline
Ordered Containers OrderedStructure Interface OrderedStructure Example OrderedVector class OrderedList class
©Duane Szafron 2003
4
Ordered ContainersOrdered Containers
An ordered container is a container whose elements are ordered by comparing them with each other.
This requires a binary operation to be defined that applies to any pair of elements that can be added to the container.
In Java, we use the compareTo(Object) method from the Comparable Interface.
As each element is added to the container it immediately goes to the proper location in the container based on comparing it with all other elements that are in the container.
©Duane Szafron 2003
5
OrderedStructure HierarchyOrderedStructure Hierarchy
The structure package adds the OrderedStructure interface below the Collection interface.
Store
Collection
List OrderedStructure
©Duane Szafron 2003
6
Structure Interface - StoreStructure Interface - Store
public interface Store {public int size();//post: returns the number of elements contained in // the store.
public boolean isEmpty();// post: returns the true iff store is empty.
public void clear();// post: clears the store so that it contains no // elements.
}
code based on Bailey pg. 18
©Duane Szafron 2003
7
Structure Interface - CollectionStructure Interface - Collection
public interface Collection extends Store {public boolean contains(Object anObject);// pre: anObject is non-null// post: returns true iff the collection contains the object
public void add(Object anObject);// pre: anObject is non-null// post: the object is added to the collection. The // replacement policy is not specified
public Object remove(Object anObject);// pre: anObject is non-null// post: removes object “equal” to anObject and returns it,// otherwise returns null
public Iterator elements();// post: return an iterator for traversing the collection
}
code based on Bailey pg. 19
©Duane Szafron 2003
8
Structure Interface - OrderedStructureStructure Interface - OrderedStructure
public interface OrderedStructure extends Collection {}
code based on Bailey pg. 173
The unusual thing about the OrderedStructure interface is that it does not add any new methods to those provided by Collection.
However, any class that implements this interface must ensure that when elements are added, they go to the correct location.
In essence, it changes the postcondition of the add method in Collection:// post: the object is added to the collection. The // replacement policy is not specified
©Duane Szafron 2003
9
OrderedStructure ExampleOrderedStructure Example
public static void main(String[] args) {
OrderedStructure container;RandomInt generator;int index;Iterator iterator;
container = new OrderedVector();generator = new RandomInt(1);for (index = 0; index < 100; index++) {
container.add(new Integer(generator.next(100)));iterator = container.elements();while(iterator.hasMoreElements())
System.out.print(iterator.nextElement() + ' ');}
code based on Bailey pg. 158
1 1 1 2 2 3 3 3 44 5 7 7 7 8 9 9 1013 13 14 14 15 17...
©Duane Szafron 2003
10
OrderedVectorOrderedVector
One implementation of OrderedStructure uses a Vector.
As each element is added, a binary search is used to put the element in the appropriate location in the Vector.
The following method will be used in the implementation of the add method and in many other methods as well.
protected int indexOf(Comparable anObject) {// pre: anObject is non-null// post: returns index of object in the collection or where// it should be placed if it is not in the collection
©Duane Szafron 2003
11
OrderedVector - OrderedVector - State and ConstructorState and Constructor
class OrderedVector implements OrderedStructure {
protected Vector data;
public OrderedVector(){// post: initializes the OrderedVector to have 0 elements
this.data = new Vector();}
code based on Bailey pg. 173
©Duane Szafron 2003
12
OrderedVector - OrderedVector - Store InterfaceStore Interface
/* Interface Store Methods */public int size() {//post: returns the number of elements contained in // the store.
return this.data.size();}
public boolean isEmpty() {// post: returns the true iff store is empty.
return this.size() == 0;}
public void clear(){// post: clears the store so that it contains no // elements.
this.data.clear();}
code based on Bailey pg. 178
©Duane Szafron 2003
13
OrderedVector - OrderedVector - contains(Object)contains(Object)
/* Interface Collection Methods */ public boolean contains(Object anObject) {
// pre: anObject is non-null// post: returns true iff the collection contains the object
int index;
index = this.indexOf((Comparable) anObject);return (index < this.size()) &&
(this.data.elementAt(index).equals(anObject));}
code based on Bailey pg. 176
©Duane Szafron 2003
14
OrderedVector - OrderedVector - add(Object)add(Object)
public void add(Object anObject){// pre: anObject is non-null// post: the object is added to the collection at the// appropriate position based on comparing it to the other// elements.
int index;
index = this.indexOf((Comparable) anObject);this.data.insertElementAt(anObject, index);
}
code based on Bailey pg. 176
©Duane Szafron 2003
15
OrderedVector - OrderedVector - remove(Object)remove(Object)
public Object remove(Object anObject){// pre: anObject is non-null// post: removes object “equal” to anObject and returns it,// otherwise returns nil
int index;Object result;
index = this.indexOf((Comparable) anObject));if (index < this.size()) && (this.data.elementAt(index).equals(anObject)) { result = this.data.elementAt(index); this.data.removeElementAt(index); return result;}return null;
}
code based on Bailey pg. 177
©Duane Szafron 2003
16
OrderedVector - OrderedVector - elements()elements()
public Iterator elements(){// post: return an iterator for traversing the collection
return this.data.elements();}
code based on Bailey pg. 177
©Duane Szafron 2003
17
The Search ProblemThe Search Problem
To complete this class, we need to solve the search problem for a sorted container.
Given a container, find the index of a particular element, called the key.
If it is not there, find the index where it should be. We use a modified version of a Binary search:
– start with one extra space since the index we are looking for may be one past the end.
– stop when there is only one element left - it is either the element we are looking for or the element should be inserted before it.
30 10 25 30 50 55 60 70 75 800 1 2 3 4 5 6 7 8 9
©Duane Szafron 2003
18
Modified Binary Search - foundModified Binary Search - found
30 middle = (low + high) / 2
high = middle - 1
HML
10 25 30 50 55 60 70 75 800 1 2 3 4 5 6 7 8 9
low = middle + 1
L HM
10 25 30 50 55 60 70 75 800 1 2 3 4 5 6 7 8 9
HH H H HL HM
10 25 30 50 55 60 70 75 800 1 2 3 4 5 6 7 8 9
©Duane Szafron 2003
19
Element not found - 1Element not found - 1
35
middle = (low + high) / 2
high = middle - 1
HML
L HM
low = middle + 1
L HM
middle = (low + high) / 2
middle = (low + high) / 2
10 25 30 50 55 60 70 75 800 1 2 3 4 5 6 7 8 9
10 25 30 50 55 60 70 75 800 1 2 3 4 5 6 7 8 9
10 25 30 50 55 60 70 75 800 1 2 3 4 5 6 7 8 9
©Duane Szafron 2003
20
Element not found - 2Element not found - 2
35
H
low = middle + 1
L HM
low < high
middle = (low + high) / 2LM
10 25 30 50 55 60 70 75 800 1 2 3 4 5 6 7 8 9
10 25 30 50 55 60 70 75 800 1 2 3 4 5 6 7 8 9
Notice that if we were looking for 50, the same steps would be taken so when (low < high) becomes false, it is either because we found the key or because the key should be inserted before the stopping index.
©Duane Szafron 2003
21
Element past end -1Element past end -1
90
middle = (low + high) / 2
HML
L HM
low = middle + 1
L HM
middle = (low + high) / 2
middle = (low + high) / 2
10 25 30 50 55 60 70 75 80
0 1 2 3 4 5 6 7 8 9
10 25 30 50 55 60 70 75 800 1 2 3 4 5 6 7 8 9
10 25 30 50 55 60 70 75 800 1 2 3 4 5 6 7 8 9
low = middle + 1
©Duane Szafron 2003
22
Element past end - 2Element past end - 2
90
H
low = middle + 1
L HM
low < high
middle = (low + high) / 2 LM
10 25 30 50 55 60 70 75 800 1 2 3 4 5 6 7 8 9
10 25 30 50 55 60 70 75 800 1 2 3 4 5 6 7 8 9
©Duane Szafron 2003
23
OrderedVector - OrderedVector - indexOf(Object) 1indexOf(Object) 1
/* Protected Methods */ protected int indexOf(Comparable anObject) {
// pre: anObject is non-null// post: returns index of object in the collection or where// it should be placed if it is not in the collection
Comparable midObject;int low;int high;int middle;int comparison;
low = 0;high = this.data.size();middle = (low + high) / 2;
code based on Bailey pg. 174
©Duane Szafron 2003
24
OrderedVector - OrderedVector - indexOf(Object) 2indexOf(Object) 2
while (low < high) { midObject = (Comparable)
this.data.elementAt(middle); comparison = midObject.compareTo(anObject); if (comparison) < 0)
low = middle + 1; else if (comparison > 0)
high = middle - 1; else
return middle; middle = (low + high) / 2;}return low; //low is either the index of the key or
} // the key should be inserted at this index.
code based on Bailey pg. 174
©Duane Szafron 2003
27
Time Complexity of OrderedVectorTime Complexity of OrderedVector
The indexOf(Object) method does O(log(n)) comparisons to find the index.
Since the contains(Object) method makes a single call to indexOf(Object), the contains(Object) method is O(log(n).
The add(Object) and remove(Object) methods also call indexOf(Object).
However, they also requires O(n) assignments to move elements in methods add(Object) and remove(Object).
Therefore, add(Object) and remove(Object) are O(n) in OrderedVector.
©Duane Szafron 2003
28
OrderedListOrderedList
We can also implement the OrderedStructure Interface using a linked list in a class called OrderedList.
However, we do not simply bind an instance variable to a linked list object like a SinglyLinkedList since we require access to the middle of the list to put added elements in the correct location.
Therefore we use SinglyLinkedListElements and link them together manually.
©Duane Szafron 2003
29
OrderedList - OrderedList - difference from OrderedVectordifference from OrderedVector
The important difference between OrderedList and OrderedVector is that the internal implementation of OrderedVector has access to the indexes of the underlying Vector elements.– This allows us to find the index of a particular element so
that it can be found, added, or removed.– It also allows us to do a binary search since we can divide
the search list in half using the indexes.
©Duane Szafron 2003
30
OrderedList - Sequential SearchOrderedList - Sequential Search
In OrderedList, we create an analog of the indexOf(Object) method called previousOf(Object) which returns the node before the node containing the object, or the node before the node where the object should be inserted.
Unfortunately, we must do a sequential search instead of a binary search.
However, we can stop early if we encounter an element that is larger than the one we are looking for.
©Duane Szafron 2003
31
OrderedList - OrderedList - State and ConstructorState and Constructor
public class OrderedList implements OrderedStructure {
protected SinglyLinkedListElement head;protected int count;
public OrderedList(){// post: initializes the OrderedList to have 0 elements
this.clear();}
code based on Bailey pg. 180
©Duane Szafron 2003
32
OrderedList - OrderedList - Store InterfaceStore Interface
/* Interface Store Methods */public int size() {//post: returns the number of elements in the store.
return this.count;}
public boolean isEmpty() {// post: returns the true iff store is empty.
return this.size() == 0;}
public void clear(){// post: clears the store so that it contains no // elements.
this.head = null;this.count = 0;
}
code based on Bailey pg. 180
©Duane Szafron 2003
33
OrderedList - OrderedList - elements()elements()
public Iterator elements(){// post: return an iterator for traversing the collection
return new SinglyLinkedListIterator(this.head);}
code based on Bailey pg. 182
©Duane Szafron 2003
34
OrderedList - OrderedList - previousOf(Object) 1previousOf(Object) 1
/* Protected Methods */ protected SinglyLinkedListElement previousOf(Object anObject)
{// pre: anObject is non-null// post: returns the node before the node that contains the// given object, if the object is in the collection or the// node before where it should be placed if it is not in the // collection
SinglyLinkedListElement cursor;SinglyLinkedListElement previous;Comparable key;
cursor = this.head;previous = null;key = (Comparable) anObject;
code based on Bailey pg. 181
©Duane Szafron 2003
35
OrderedList - OrderedList - previousOf(Object) 2previousOf(Object) 2
while ((cursor != null) && (((Comparable) cursor.value()).compareTo(key) < 0)) { previous = cursor; cursor = cursor.next();}return previous;
}
code based on Bailey pg. 181
©Duane Szafron 2003
36
OrderedList - OrderedList - contains(Object)contains(Object)
/* Interface Collection Methods */ public boolean contains(Object anObject) {
// pre: anObject is non-null// post: returns true iff the collection contains the object
SinglyLinkedListElement previous;SinglyLinkedListElement current;
previous = this.previousOf((Comparable) anObject);if (previous == null) // no previous element, first node current = this.head;else current = previous.next();if (current == null) return false;else return current.value().equals(anObject);
}
code based on Bailey pg. 180