Ordered Structures

advertisement
Ordered Containers
CMPUT 115 - Lecture 19
Department of Computing Science
University of Alberta
©Duane Szafron 2003
Some code in this lecture is based on code from the book:
Java Structures by Duane A. Bailey or the companion structure package
2
About 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
Outline





Ordered Containers
OrderedStructure Interface
OrderedStructure Example
OrderedVector class
OrderedList class
©Duane Szafron 2003
4
Ordered 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 Hierarchy

The structure package adds the
OrderedStructure interface below the
Collection interface.
Store
Collection
List
©Duane Szafron 2003
OrderedStructure
6
Structure 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.
}
©Duane Szafron 2003
code based on Bailey pg. 18
7
Structure 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
}
©Duane Szafron 2003
code based on Bailey pg. 19
8
Structure Interface - OrderedStructure
public interface OrderedStructure extends Collection {}



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
code based on Bailey pg. 173
9
OrderedStructure Example
public static void main(String[] args) {
OrderedStructure
RandomInt
int
Iterator
container;
generator;
index;
iterator;
1 1 1 2 2 3 3 3 4
4 5 7 7 7 8 9 9 10
13 13 14 14 15 17
...
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() + ' ');
}
©Duane Szafron 2003
code based on Bailey pg. 158
10
OrderedVector



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 - State and Constructor
class OrderedVector implements OrderedStructure {
protected Vector data;
public OrderedVector(){
// post: initializes the OrderedVector to have 0 elements
this.data = new Vector();
}
©Duane Szafron 2003
code based on Bailey pg. 173
12
OrderedVector - Store 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();
}
©Duane Szafron 2003
code based on Bailey pg. 178
13
OrderedVector - 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));
}
©Duane Szafron 2003
code based on Bailey pg. 176
14
OrderedVector - 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);
}
©Duane Szafron 2003
code based on Bailey pg. 176
15
OrderedVector - 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;
}
©Duane Szafron 2003
code based on Bailey pg. 177
16
OrderedVector - elements()
public Iterator elements(){
// post: return an iterator for traversing the collection
return this.data.elements();
}
©Duane Szafron 2003
code based on Bailey pg. 177
17
The 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
0 1 2 3 4 5 6 7 8
10 25 30 50 55 60 70 75 80
©Duane Szafron 2003
9
18
Modified Binary Search - found
30
middle = (low + high) / 2
H
L
M
H LM
HH
M
H
H
0 1 2 3 4 5 6 7 8 9
10 25 30 50 55 60 70 75 80
high
low ==middle
middle+- 1
©Duane Szafron 2003
19
Element not found - 1
middle = (low + high) / 2
35
L
M
H
0 1 2 3 4 5 6 7 8 9
10 25 30 50 55 60 70 75 80
high = middle - 1
middle = (low + high) / 2
L
M
H
0 1 2 3 4 5 6 7 8 9
10 25 30 50 55 60 70 75 80
low = middle + 1
middle = (low + high) / 2
LM
H
0 1 2 3 4 5 6 7 8
10 25 30 50 55 60 70 75 80
©Duane Szafron 2003
9
20
Element not found - 2
35
LM
H
0 1 2 3 4 5 6 7 8 9
10 25 30 50 55 60 70 75 80
low = middle + 1
middle = (low + high) / 2
MLH
0 1 2 3 4 5 6 7 8
10 25 30 50 55 60 70 75 80

9
low < high
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 -1
middle = (low + high) / 2
90
L
M
H
0
1
2
3
4
5
6
7
8
10
25
30
50
55
60
70
75
80
middle = (low + high) / 2
L
M
0 1 2 3 4 5 6 7 8
10 25 30 50 55 60 70 75 80
9
low = middle + 1
H
9
ML H
middle = (low + high) / 2
0 1 2 3 4 5 6 7 8 9
10 25 30 50 55 60 70 75 80
©Duane Szafron 2003
low = middle + 1
22
Element past end - 2
90
LM
H
0 1 2 3 4 5 6 7 8
10 25 30 50 55 60 70 75 80
9
middle = (low + high) / 2
0 1 2 3 4 5 6 7 8
10 25 30 50 55 60 70 75 80
©Duane Szafron 2003
low = middle + 1
LMH
9
low < high
23
OrderedVector - indexOf(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;
©Duane Szafron 2003
code based on Bailey pg. 174
24
OrderedVector - indexOf(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.
©Duane Szafron 2003
code based on Bailey pg. 174
25
©Duane Szafron 2003
26
©Duane Szafron 2003
27
Time 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
OrderedList

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 - difference 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 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 - State 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();
}
©Duane Szafron 2003
code based on Bailey pg. 180
32
OrderedList - Store 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;
}
©Duane Szafron 2003
code based on Bailey pg. 180
33
OrderedList - elements()
public Iterator elements(){
// post: return an iterator for traversing the collection
return new SinglyLinkedListIterator(this.head);
}
©Duane Szafron 2003
code based on Bailey pg. 182
34
OrderedList - previousOf(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;
©Duane Szafron 2003
code based on Bailey pg. 181
35
OrderedList - previousOf(Object) 2
while ((cursor != null) && (((Comparable)
cursor.value()).compareTo(key) < 0)) {
previous = cursor;
cursor = cursor.next();
}
return previous;
}
©Duane Szafron 2003
code based on Bailey pg. 181
36
OrderedList - 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);
}
©Duane Szafron 2003
code based on Bailey pg. 180
Download