Containers and Iterators The safe array class VectorInfo is an example of a “container” class:...

46
Containers and Iterators afe array class VectorInfo is an example o ainer” class: #include <iostream.h> #include <assert.h> typedef int Integer; typedef Integer * IntegerArray; typedef class VectorInfo * Vector; class VectorInfo { private: IntegerArray p; Integer size; public: VectorInfo(Integer n); ~VectorInfo(); Integer& element(Integer i); };

Transcript of Containers and Iterators The safe array class VectorInfo is an example of a “container” class:...

Page 1: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Containers and Iterators

The safe array class VectorInfo is an example of a“container” class:

#include <iostream.h>#include <assert.h>

typedef int Integer;typedef Integer * IntegerArray;typedef class VectorInfo * Vector;

class VectorInfo {private: IntegerArray p; Integer size;public: VectorInfo(Integer n); ~VectorInfo(); Integer& element(Integer i);};

Page 2: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

VectorInfo Class ImplementationVectorInfo::VectorInfo(Integer n){ assert ( n >= 1 ); size = n; p = new Integer[size]; assert (p != 0); for (Integer i = 0; i < n; i++) { // for demo purposes p[i] = i; // we fill array } // with index values}

VectorInfo::~VectorInfo() { delete [] p; }

Integer& VectorInfo::element(Integer i){ assert (i >= 0 && i <= size); return (p[i]);}

Page 3: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

VectorInfo Class ApplicationFind the median value in a sorted Vector of n valuesby moving pointers from endpoints until they meet:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14

front back0 1 2 3 4 5 6 7 8 9 10 11 12 13 14

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14

front back

backfront......

Page 4: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

VectorInfo Class Application (cont'd)

Vector a = new VectorInfo(n);

Integer front_index = 0; Integer back_index = n;

Integer front = a->element(front_index++); Integer back = a->element(--back_index);

while ( front < back ) { cout << setw(5) << front << setw(5) << back << endl; front = a->element(front_index++); back = a->element(--back_index); } cout << "Middle value is " << front << endl;

Page 5: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Program Output for n = 15

6% a.out 0 14 1 13 2 12 3 11 4 10 5 9 6 8Middle value is 77%

Page 6: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Decoupling Index Handling from Loops

● The example has 6 places where Vector loop indexes have to be (confusingly!) managed:– front_index points directly to the next value– back_index does not– front_index is incremented after its use– back_index is decremented before its use

● Therefore, 6 opportunities for errors● Good OOP style prefers to keep index management

hidden from the implementor of the loop

Page 7: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Decoupling Index Handling: First Try

Instead of: Integer n = 15; Vector a = new VectorInfo(n); for (Integer i = 0; i < n; i++) cout << setw(4) << a->element(i); cout << endl;

Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14

We would like: Integer n = 15; Vector a = new VectorInfo(n); for (Integer i = 0; i < n; i++) cout << setw(4) << a->next(); cout << endl;

Page 8: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Revised VectorInfo Class Definition

class VectorInfo {private: IntegerArray p; Integer size; Integer index; // Store index as part // of the objectpublic: VectorInfo(Integer n); ~VectorInfo(); Integer& element(Integer i); Integer& next(); // Let this method keep}; // track of the index

Page 9: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Revised VectorInfo Methods

VectorInfo::VectorInfo(Integer n){ assert ( n >= 1 ); size = n; p = new Integer[size]; assert (p != 0); for (Integer i = 0; i < n; i++) { p[i] = i; } index = 0; // Point index to beginning}

Integer& VectorInfo::next() { // Note circular if (index == size) // visitation return element(index = 0); else return element(index++);}

Page 10: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Eliminating Index Handling Entirely

Integer n = 15; Vector a = new VectorInfo(n); while ( a->hasNext() ) cout << setw(4) << a->next(); cout << endl;

Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14

Page 11: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

New VectorInfo Class

class VectorInfo {private: IntegerArray p; Integer size; Integer index; public: VectorInfo(Integer n); ~VectorInfo(); Integer& element(Integer i); Integer& next(); Boolean hasNext(); };

Boolean VectorInfo::hasNext() { return (index < size); }

Page 12: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Trade-Offs● Advantage: index handling is performed by the class,

so coding is safer● Disadvantage 1: container class is beginning to not

have a single purpose● Disadvantage 2: Consider original example, in which

two indexes are needed:– front_index– back_index– However, as it stands, visitation over a Vector object is

restricted to one use, since there is one index– Like restricting a museum to one patron at a time

Page 13: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Possible Remedies

● Create multiple copies of the object– like creating multiple musems for multiple patrons

● Add multiple indexes to the class definition– How many? Can't know in advance– Makes container class even more complex

● Best solution: create an iterator class:– Sole purpose is to handle visitation of a container object– Multiple iterators can be created for one container– Like letting anyone in to the museum without knowing

how many

Page 14: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Iterator Classes

● Iterator classes handle the details of container visitation:– keep track of current index– implement hasNext() method– implement next() method

● Iterator class object must contain a pointer to the container it is iterating over

● When more than one iterative use of a container is needed, create more iterator objects (not more containers)

Page 15: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Class Diagram

VectorInfo

p: IntegerArrarysize: Integer

VectorInfo(n: Integer)~VectorInfo()element(i: Integer): IntegergetSize(): Integer

VectorIterInfo

index: Integer

VectorIterInfo(v: Vector)next(): IntegerhasNext(): Boolean

Vector *

Page 16: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

VectorIterInfo Implementation

VectorIterInfo::VectorIterInfo(Vector v) { vector = v; index = 0;}

Integer& VectorIterInfo::next() { if ( index == vector->getSize() ) return vector->element(index = 0); else return vector->element(index++); }

Boolean VectorIterInfo::hasNext() { return (index < vector->getSize()); }

Page 17: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

VectorIterInfo Example

Vector a = new VectorInfo(15); VectorIter iter = new VectorIterInfo(a); while ( iter->hasNext() ) cout << setw(4) << iter->next(); cout << endl;

Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14

Page 18: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Using Multiple Iterators

Vector a = new VectorInfo(5); VectorIter iter1 = new VectorIterInfo(a); VectorIter iter2 = new VectorIterInfo(a);

while ( iter1->hasNext() ) { Integer outer = iter1->next(); while ( iter2->hasNext() ) { Integer inner = iter2->next(); cout << setw(5) << outer * inner; } cout << endl; iter2->next(); } cout << endl; 0 0 0 0 0

0 1 2 3 4 0 2 4 6 8 0 3 6 9 12 0 4 8 12 16

Output:

Page 19: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Enhancing the VectorIterInfo Class

● Our initial example (finding median value in a sorted vector) requires iterating backward as well as forward

● So we can add the methods:– previous()– hasPrevious()

● We also need the ability to reset the index to a desired value (not just 0):– reset(Integer)

● We will also eliminate circular visitation

Page 20: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

New VectorIterInfo Class

class VectorIterInfo { private: Vector vector; Integer index; public: VectorIterInfo(Vector v); Integer& next(); Integer& previous(); Boolean hasNext(); Boolean hasPrevious(); void reset(Integer i);};

Page 21: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

New VectorIterInfo Methods

Integer& VectorIterInfo::previous() {// Note no circular if ( index == 0 ) // visitation. This throw "There is no previous."; // throw should be else // caught by the app return vector->element(--index); }

Boolean VectorIterInfo::hasPrevious() { return (index > 0); }

void VectorIterInfo::reset(Integer i) { index = i;}

Note that the next() method should also throw if there is no next element.

Page 22: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Original Example Again Integer n = 15; Vector a = new VectorInfo(n); VectorIter forward = new VectorIterInfo(a); forward->reset(0); VectorIter backward = new VectorIterInfo(a); backward->reset(n);

Integer front = forward->next(); Integer back = backward->previous();

while ( front < back ) { cout << setw(5) << front << setw(5) << back << endl; front = forward->next(); back = backward->previous(); } cout << "Middle value is " << front << endl;

This code should be enclosed in a try block with anappropriate catch clause.

Page 23: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Output

0 14 1 13 2 12 3 11 4 10 5 9 6 8Middle value is 7

Page 24: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Application: quickSort

10

716

4 918

-3 812

-3 4 7 8 910

12

16

18

Input:

Output:

Constraints: Perform the sort ``in place'' (no other memory is used)

Page 25: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

quickSort Trace

10

716

4 9

comparisonelement

from to

18

-3 812

Page 26: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

quickSort Trace (cont'd)

10

716

4 9

comparisonelement

from to

18

-3 812

18

16

12-3 7 8 4

109

partitioneverything less thancomparison element

everything greater thanor equal to comparison element

Page 27: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

quickSort Trace (cont'd)

10

716

4 9

comparisonelement

from to

18

-3 812

18

16

12-3 7 8 4

109

partition

-3 7 8 4 9

partition16

12

18

partition

everything less thancomparison element

everything greater thanor equal to comparison element

Page 28: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

quickSort Trace (cont'd)

10

716

4 9

comparisonelement

from to

18

-3 812

18

16

12-3 7 8 4

109

partition

-3 7 8 4 9

partition

4 7 8 9

16

12

18

partition

12

16

swappartition

everything less thancomparison element

everything greater thanor equal to comparison element

Page 29: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

quickSort Trace (cont'd)

10

716

4 9

comparisonelement

from to

18

-3 812

18

16

12-3 7 8 4

109

partition

-3 7 8 4 9

partition

4 7 8 9

16

12

18

partition

12

16

swap

-3 4 7 8 910

12

16

18

partition

everything less thancomparison element

everything greater thanor equal to comparison element

final sorted vector

Page 30: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

The partition Procedure

10

716

4 9

comparisonelement

from to

18

-3 812

10

716

4 918

-3 812

iterate up until out-of-place element found:

10

716

4 918

-3 812

iterate down until out-of-place element found:

10

7 8 4 918

-316

12

swap:

10

7 8 4 9 -318

16

12repeat:

-3 7 8 4 910

18

16

12

swap comparison elementwith appropriate element:

Page 31: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

A SortInfo Class

class SortInfo {public: void quickSort(Vector v, Integer from, Integer to);private: void swap(Integer& i, Integer& j); Integer partition(Vector v, Integer from, Integer to);};

Page 32: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Example Using SortInfo Integer n; cout << "Enter Size: "; cin >> n; cout << "\nEnter elements: ";

Vector v = new VectorInfo(n); VectorIter front = new VectorIterInfo(v); front->reset(0);

while ( front->hasNext() ) { cin >> front->getItem(); front->next(); } cout << endl;

v->print(); Sort s = new SortInfo(); s->quickSort(v, 0, n-1); v->print();

Page 33: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Example Output

Enter Size: 9

Enter elements: 10 7 16 4 9 18 -3 8 12

10 7 16 4 9 18 -3 8 12 -3 4 7 8 9 10 12 16 18

Page 34: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Implementing quickSort with Iterators

● quickSort is easy to write recursively● The more complex procedure is partition,

which we will implement with iterators● Changes necessary for VectorInfo:

– Add print() method● Changes necessary for VectorIterInfo:

– Add getIndex() accessor– Add getItem() that returns the item at the current

index

Page 35: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

SortInfo::quickSort Method

void SortInfo::quickSort(Vector v, Integer from, Integer to) { Integer mid; if (from < to) { if (from == to - 1) { //2 elements if ( v->element(from) > v->element(to) ) swap(v->element(from), v->element(to)); } else { mid = partition(v, from, to); quickSort(v, from, mid - 1); quickSort(v, mid + 1, to); } }}

Page 36: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

SortInfo::Partition MethodInteger SortInfo::partition(Vector v, Integer from, Integer to) { VectorIter front = new VectorIterInfo(v); VectorIter back = new VectorIterInfo(v); Integer compare;

back->reset(to); front->reset(from); compare = front->next(); //comparison element

while (front->getIndex() < back->getIndex()) {

// Search forward while ((front->getIndex() < back->getIndex()) &&(compare > front->getItem())) front->next();

// Search backward while ((front->getIndex() < back->getIndex()) &&(compare <= back->getItem())) back->previous();

// Exchange items swap(front->getItem(), back->getItem()); } ...

Page 37: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

SortInfo::Partition Method (cont'd)

... //insert mid position comparison element

if (compare >= front->getItem()) { swap(v->element(from), front->getItem()); return (front->getIndex()); } else { // in case pointers crossed in last iteration swap(v->element(from), v->element(front->getIndex() - 1) ); return (front->getIndex() - 1); }}

Page 38: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Analysis of quickSort

We will count the number of data movements thatquickSort does.

To do this we will use a recursion tree. We start withthe original vector as root:

0 N-1

Page 39: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Analysis of quickSort (cont'd)

0 N-1

After one call to partition:

Q: What is the maximum number of data movements necessary by this call to partition?

A: Movements per swap * Maximum swaps = 3 * N = O(N)

Page 40: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Analysis of quickSort (cont'd)

0 N-1

After two more calls to partition:

Q: What is the maximum number of data movements necessary for the second level?

A: movements per swap * maximum swaps = 3 * (2 * N/2) = 3 * N O(N)

Page 41: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Analysis of quickSort (cont'd)

● There are O(N) data movements per level of the recursion tree

● So the total number of data movements is:– O(N) * the number of levels

● How many levels are there?– Answer: the height of the recursion tree, which

depends upon the nature of the original data

Page 42: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Assuming Vector Values are Randomly Distributed0 N-1

Q: What is the height of this tree?

Page 43: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Assuming Vector Values are Randomly Distributed (cont'd)

N Levels 2 1 4 2 8 316 4 ... N log2N

Page 44: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Assuming Vector is Already Sorted or Nearly Sorted

0 N-1

. . .

.

.

.

Q: What is the height of this tree?A: N

Page 45: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Analysis of quickSort (Summary)

● The total number of data movements done by quickSort is:– O(Nlog(N)) if vector values are randomly distributed– O(N2) if vector is already sorted or nearly sorted

● In worst case, quickSort is no better than bubble sort, insertion sort, or selection sort

● In average case, quickSort is among the best● Analysis can proceed by counting other actions,

like comparisons, but results are similar

Page 46: Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include typedef int Integer; typedef Integer * IntegerArray;

Efficiency Comparisons

0 N

O(N)array implementationof priority queue

O(logN)binary heapimplementationof priority queue

O(bN)minimaxValue

time

O(NlogN)quicksort

O(N2)bubblesort