View
229
Download
2
Tags:
Embed Size (px)
Citation preview
Sequences
R e c a l l t h a t w i t h a v e c t o r , w e u s e r a n k t o a c c e s s e l e m e n t s . W i t h a l i s t , w e u s e p o s i t i o n t o a c c e s s e l e m e n t s .
S E Q U E N C E
0 1 2 3 4 5 6 7
sequenc: A container of elements, that stores elements in a linear order and that provides both rank and position to access each element. Example: Consider the salesman’s schedule as a sequence 0 1 2 3 4 5 Halifax Montreal Ottawa Toronto Winnipeg Regina 6 7 Edmonton Vancouver We can use the rank ( 4 ) to access the element “Winnipeg” Or we can find Winnipeg is after Toronto and before Regina (position).
The Sequence Abstract Data Type
The sequence abstract data type supports all the methods of both the vector ADT and list ADT, plus the following two “bridging” methods that provide connections between ranks and positions: atRank(r): Return the position of the element with rank r.
Input: Integer; Output: Position rankOf(p): Return the rank of the element at position p.
Input: Position; Output: Integer
I n J a v a , th e in te r f a c e fo r s e q u e n c e s i s a n e x a m p le o f m u lt ip le in h e r i t a n c e : i n t e r f a c e S e q u e n c e e x t e n d s L i s t , V e c t o r { p u b l i c P o s i t i o n a t R a n k ( i n t r a n k ) t h r o w s B o u n d a r y V i o l a t i o n E x c e p t i o n ; p u b l i c i n t r a n k O f ( P o s i t i o n p o s i t i o n ) t h r o w s I n v a l i d P o s i t i o n E x c e p t i o n ; }
V e c to r i n te r f a c e L is t i n te r fa c e
S e q u e n c e i n te r fa c e
Implementing a Sequence
Recall that an array can be used to implement a vector. And a doubly linked list can be used to implement a list. We can implement a sequence with either an array or a doubly linked list. We study implementing a sequence with a doubly liked list first.
Sequence ADT Position rank
Doubly linked list DNode atRank(r)rankOf(p)
Implementation of a sequence with a doubly linked list:
Implementing a Sequence with a Doubly Linked List
R e c a l l t h a t p o s i t i o n o p e r a t i o n s c a n b e e a s i l y i m p l e m e n t e d w i t h a d o u b l y l i n k e d l i s t . H o w e v e r , i t i s n o t e a s y t o i m p l e m e n t r a n k o p e r a t i o n s . T o f i n d a n e l e m e n t f o r a g i v e n r a n k , w e h a v e t o p e r f o r m l i n k h o p p i n g . E x a m p l e : W e h a v e t o “ h o p ” t w i c e t o f i n d t h e e l e m e n t a t r a n k 2
h e a d e r
R o m e S e a t t l e
t r a i l e r
B a l t i m o r eT o r o n t o
10 2 3
Class NodeSequence
In Java, we declare a class NodeSequence to implement sequences. The class inherites the class NodeList and implements the interface Sequence: public class NodeSequence extends NodeList implements Sequence { . . . }
The methods to be implemented in class NodeSequence:
Methods defined in Vector:void insertAtRank(int rank, Object element)Object removeAtRank(int rank)Object replaceAtRank(int rank, Object element)Object elemAtRank (int r)
Auxiliary method:void checkRank(int rank, int range)
Bridging methods:Position atRank(int rank)rankOf(Position p)
protected void checkRank( int rank, int s ) throws BoundaryViolationException { if( rank < 0 || rank >= s ) throw new BoundaryViolationException( "Rank" + rank + " is invalid for this sequence of " + numElts + " elements." ); }
This method checks if the given rank is out of boundary.
public Position atRank( int rank ) { DNode node;
int n = size();
checkRank( rank, n ); if( rank <= n / 2 ) { node = header.getNext(); for( int i = 0; i < rank; i++ ) { node = node.getNext(); } } else { node = trailer.getPrev(); for( int i = 1; i < n - rank; i++ ) { node = node.getPrev(); } } return node; }
0 1 r2 n-2 n-1
Number of hopping = ri=0,1,...,r-1
Number of hopping = n-r-1i=1,2,...,n-r-1
n-3
rank number of hopping 0 0 1 1 2 2 3 3 … … r r rank number of hopping n-1 0 n-2 1 n-3 2 n-4 3 … … r n-r-1
public void insertAtRank( int rank, Object element ) throws BoundaryViolationException { if( rank == size() ) { insertLast( element ); } else { checkRank( rank, size() ); insertBefore( atRank( rank ), element ); } }
0 1 r
e
2
0 1 r
e
2
public Object removeAtRank( int rank ) throws BoundaryViolationException { checkRank( rank, size() ); return remove( atRank( rank )); }
0 1 r
e
2
0 1 r
e
2
public Object replaceAtRank( int rank, Object element ) throws BoundaryViolationException { checkRank( rank, size() ); return replaceElement( atRank( rank ), element ); }
0 1 r
o
2
e
0 1 r2
e
/** Gets an element at the given rank.*/ public Object elemAtRank(int r) { return atRank(r).element(); }
/** Returns the rank of a given position.*/ public int rankOf(Position p) { DNode node; node = header.getNext(); for (int i=1; i < size(); i++) {
if (p == node) return i;else node = node.getNext();}
} }
/** Implementation of a sequence by means of a doublylinked list. */
public class NodeSequence extends NodeList implementsSequence {
/** Checks whether the given rank is in the range [0, n - 1] */
protected void checkRank(int r, int n) throws BoundaryViolationException { if (r < 0 || r >= n) throw new
BoundaryViolationException("Illegal rank: " + r); }
/** Returns the position containing the element atthe given rank; O(n) time. */
public Position atRank (int rank) { DNode node; checkRank(rank, size()); if (rank <= size()/2) { // scan forward from the head node = header.getNext(); for (int i=0; i < rank; i++)
node = node.getNext(); } else { // scan backward from the tail node = trailer.getPrev(); for (int i=1; i < size()-rank; i++)
node = node.getPrev();} return node; }
/** Gets an element at the given rank.*/ public Object elemAtRank(int r) { return atRank(r).element(); } /** Returns the rank of a given position.*/ public int rankOf(Position p) { DNode node; node = header.getNext(); for (int i=1; i < size(); i++) {
if (p == node) return i;else node = node.getNext();}
} }
/** Inserts an element at the given rank; O(n) time. */ public void insertAtRank (int rank, Object element) throws BoundaryViolationException { checkRank(rank, size() + 1); if (rank == size()) insertLast(element); else { insertBefore(atRank(rank), element); } }
/** Removes the element stored at the given rank;O(n) time. */
public Object removeAtRank (int rank) throws BoundaryViolationException { checkRank(rank, size()); return remove(atRank(rank)); }
public Object replaceAtRank(int rank, object element) throws BoundadryViolationException { checkRank(rank); return replaceElement(atRank(rank), element); } }
Implementing a Sequence with an Array
R e c a l l t h a t w i t h a n a r r a y , r a n k o p e r a t i o n s a r e e a s y . W h a t c a n b e u s e d t o r e p r e s e n t a p o s i t i o n ? W e c a n n o t u s e i n d e x t o r e p r e s e n t a p o s i t i o n b e c a u s e i n d e x c a n c h a n g e w h i l e t h e p o s i t i o n d o e s n o t .
q p s
0 1 2 3 4 5 6
A f t e r t h e f i r s t e l e m e n t ( r a n k 0 ) i s r e m o v e d :
q p s
0 1 2 3 4 5
The solution is that we use an array to store the references to position objects. In turn, each position object stores the rank and a reference to the element.
0
1 2
3 N-1
0
1 2
3
Baltimore New York Rome Providence
S
Let us consider the insertFirst(e) method. Before insertFirst(e):
0
1 2
3 N-1
0
1 2
3
Baltimore New York Rome Providence
S
C re a te a n e w p o s i t io n a n d m a k e ro o m fo r i t . U p d a te in d e x fo r e a c h e le m e n t .
0
2 3
4 N - 1
1
1 2
4
B a l tim o re N e w Y o rk R o m e P ro v id e n ce
S
0
T o ro n to
3
A f te r in s e r tF i r s t ( e ) :
0
2 3
4 N - 1
1
1 2
4
B a l ti m o r e N e w Y o r k R o m e P r o v i d e n c e
S
0
T o r o n t o
3
B e c a u s e i t n e e d s to u p d a te th e in d e c e s a n d m a k e r o o m f o r th e n e w e le m e n t , th e r u n n in g t im e o f th is o p e r a t io n i s p r o p o r t io n a l to n , th e s iz e o f th e s e q u e n c e
Comparing Sequence Implementations
The table here is a comparison of the running times. Operations Array List size, isEmpty fast fast atRank, rankOf, elementAtRank fast )(nO first, last, before,after fast fast replaceElement, swapElements fast fast replaceAtRank fast )(nO insertAtRank, removeAtRank )(nO )(nO insertFirst, insertLast fast fast inserAfter, inserBefore )(nO fast
remove )(nO fast
Interface Hierarchy for Vectors, Lists, and Sequences
Vector (interface) List (interface)
Sequence (interface)ArrayVector (class) NodeList (class)
ArraySequence (class) NodeSequence (class)
impl. extends extends
impl. impl. extendsextends
Supplement with the methodsin Vector interface
Supplement with the methodsin List interface
impl.
Data Structure Exercises 9.1
IteratorsS o f a r , w e h a v e s e e n t h a t t h e r e a r e t i m e s w h e n w e w a n t t o p r o c e s s e a c h e l e m e n t s i n a v e c t o r o r a l i s t .
S E Q U E N C E
0 1 2 3 4 5 6 7
F o r a v e c t o r , w e p r o c e s s t h e e l e m e n t s u s i n g r a n k s . F o r a l i s t , w e p r o c e s s t h e e l e m e n t s u s i n g p o s i t i o n . S i n c e s u c h a n o p e r a t i o n i s s o p o p u l a r , w e c a n d e f i n e a n a b s t r a c t d a t a t y p e f o r i t , c a l l e d i t e r a t o r .
i t e r a t o r : T h e p r o c e s s o f s c a n n i n g t h r o u g h a c o l l e c t i o n o f e l e m e n t s o n e e l e m e n t a t a t i m e . W h e n w e w a n t t o s c a n t h r o u g h a s e q u e n c e , w h a t c o n c e r n s u s i s t h e f o l l o w i n g q u e s t i o n s : 1 . I s t h e n e x t e l e m e n t a v a i l a b l e ? 2 . W h a t i s t h e n e x t e l e m e n t i f i t i s a v a i l a b l e ?
C u r r e n t p o s i t i o n
N e x t p o s i t i o n
S
The Iterator Abstract Data Type
The iterator abstract data type supports the following methods:
hasNext(): Test whether there are elements left in the iterator. Input: None; Output: Boolean
next(): Return and remove the next element in the iterator. Input: None; Output: Object
Iterators in Java
Java provides an Iterator interface.
public interface Iterator { boolean hasNext(); Object next(); }
(in package java.util)
An implementation of the Iterator is always related to container,i.e., a vector, a list, or a sequence.
The following is an exemplary implementation of the List Iterator.
public class PositionIterator implements Iterator { protected List list; // the underlying list protected Position cur;
// the current (next) position public PositionIterator() { } // default constructor public PositionIterator(List L) {
// preferred constructor list = L; if (list.isEmpty()) cur = null; // list is empty else cur = list.first();
// start with the first position }
public boolean hasNext() { return (cur != null); }public Object next() throws NoSuchElementException {
if (!hasNext())throw new NoSuchElementException("No next position");
Position toReturn = cur; if (cur == list.last()) cur = null;
// no positions left else { try {
cur = list.after(cur)}catch (InvalidPositionException e) { }
} // move cursor to the next position return toReturn; }}
class NoSuchElementException extends Exception { public NoSuchElementException() {super();} public NoSuchElementException(String s) { super(s); }}
In a similar way, we can establish an ElementIterator as follows.
public class ElementIterator implements Iterator { protected List list; // the underlying list protected Position cur;
// the current (next) position protected Object elementCur;
// the current (next) element public ElementIterator() { }
// default constructor public ElementIterator(List L) {
// preferred constructor list = L; if (list.isEmpty()) cur = null; // list is empty else cur = list.first();
// start with the first position }
public boolean hasNext() { return (cur != null); } public Object next() throws NoSuchElementException { if (!hasNext())
throw newNoSuchElementException("No next position");
elementCur = cur.element(); if (cur == list.last()) cur = null;
// no positions left else { try {
cur = list.after(cur)}catch (InvalidPositionException e) { }
} // move cursor to the next position
return elementCur; }}
The following is a simple example of using the Iterator interface. public static void printVector( Vector vec ) { Iterator iter = vec.iterator(); while( iter.hasNext() ) { System.out.println( iter.next()); } }
Note: In page 215, the textbook proposes a method elements() that returns an iterator. In Java, it is the method iterator() that returns an iterator. The method elements(), on the other hand, returns an object of Enumeration. Basically, it is also an iterator.
InspectableContainersizeisEmptyelements
InspectableVectorelemAtRank
InspectableListfirstlastbeforeafterpositions
VectorreplaceAtRankinsertAtRankremoveAtRank
InspectableSequenceatRankrankOf
ListreplaceElementswapElementsinsertFirstinsertLastinsertBeforeinsertAfterremove
Sequence
Data Structure Exercises 10.1
Case Study: Bubble-Sort on a Sequence
An interesting application of sequences is to implement the well-known bubble-sort algorithm. We will study how to use sequence and what are the trade-offs with different implementations of sequences.
01260 43.21 27784 31.32 10600 37.41 23692 35.96 22673 41.76 10600 37.41 23692 35.96 22673 41.76 27784 31.32 01260 43.21 27951 47.27 82366 45.53 82366 45.53 27951 47.27
The Bubble-Sort Algorithm
The sorting problem is to reorder the sequence so that the elements are in non-decreasing order. Example: For a given sequence (5,7,2,6,9,3) we want to have it sorted so it becomes (2,3,5,6,7,9)
The algorithm: Given a sequence S assign 0 to a variable i while not done for rank r = 0 to n - i - 1 if the element S[ r ] is larger than S[ r + 1 ] swap element S[ r ] and S[ r + 1 ] increment i The for loop in the algorithm is called a pass. Therefore, the bubble sort performs a series of passes.
2, 3, 5, 6, 7, 9i
for a certain i
r
The first pass for the sequence (5,7,2,6,9,3) rank sequence after each
iteration swap
(5,7,2,6,9,3) 0 (5,7,2,6,9,3) - 1 (5,2,7,6,9,3) 7 <->2 2 (5,2,6,7,9,3) 7 <->6 3 (5,2,6,7,9,3) - 4 (5,2,6,7,3,9) 9 <->3
The second pass for the sequence (5,7,2,6,9,3) rank sequence after each iteration swap (5,2,6,7,3,9) 0 (2,5,6,7,3,9) 5 <->2 1 (2,5,6,7,3,9) - 2 (2,5,6,7,3,9) - 3 (2,5,6,3,7,9) 7 <->3
The third pass for the sequence (5,7,2,6,9,3) rank sequence after each iteration swap (2,5,6,3,7,9) 0 (2,5,6,3,7,9) - 1 (2,5,6,3,7,9) - 2 (2,5,3,6,7,9) 6 <->3
The fourth pass for the sequence (5,7,2,6,9,3) rank sequence after each iteration swap (2,5,3,6,7,9) 0 (2,5,3,6,7,9) - 1 (2,5,3,6,7,9) 5 <->3
Bubble Sort Using Rankspublic static void bubbleSort1( Sequence S ) { int n = S.size(); for( int i = 0; i < n; i++ ) for( int j = 1; j < n - i; j++ ) if( valAtRank( S, j - 1 ) > valAtRank( S, j ) S.swapElement( S.atRank( j - 1 ), S.atRank( j )); } private static int valAtRank( Sequence S, int i ) { return (( Integer ) S.elemAtRank( i )).intValue(); }
If the sequence is array-based, the running time is proportional tothe square of n, the size of the sequence: running time O(n2). On the other hand, if the sequence is position-based, the runningtime is proportional to n3. running time O(n3). In this case, the atRank operation needs to perform link hopping.
Bubble Sort Using Positionspublic static void bubbleSort2( Sequence S ) { Position prec, succ; int n = S.size(); for( int i = 0; i < n; i++ ) { prec = S.first(); for( int j = 1; j < n - i; j++ ) { succ = S.after( prec ); if( valAtPos( prec ) > valAtPos( succ ) S.swapElements( prec, succ ); prec = succ; } } } private static int valAtPos( Position p ) { return (( Integer )p.element()).intValue(); }
The running time is proportional to the square of n, the size of thesequence, regardless of how the sequence is implemented: running time O(n2).
Data Structure Exercises 9.2