Download presentation
Presentation is loading. Please wait.
Published byPoppy Hodges Modified over 9 years ago
1
Containers and Iterators The safe array class VectorInfo is an example of a “container” class: #include 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); };
2
VectorInfo Class Implementation VectorInfo::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]); }
3
VectorInfo Class Application Find the median value in a sorted Vector of n values by moving pointers from endpoints until they meet: 01234567891011121314 frontback 01234567891011121314 01234567891011121314 frontback front...
4
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;
5
Program Output for n = 15 6% a.out 0 14 1 13 2 12 3 11 4 10 5 9 6 8 Middle value is 7 7%
6
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
7
Decoupling Index Handling: First Try Instead of: Integer n = 15; Vector a = new VectorInfo(n); for (Integer i = 0; i < n; i++) cout 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 next() ; cout << endl;
8
Revised VectorInfo Class Definition class VectorInfo { private: IntegerArray p; Integer size; Integer index; // Store index as part // of the object public: VectorInfo(Integer n); ~VectorInfo(); Integer& element(Integer i); Integer& next(); // Let this method keep }; // track of the index
9
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++); }
10
Eliminating Index Handling Entirely Integer n = 15; Vector a = new VectorInfo(n); while ( a->hasNext() ) cout next(); cout << endl; Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
11
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); }
12
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
13
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
14
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)
15
Class Diagram VectorInfo p: IntegerArrary size: Integer VectorInfo(n: Integer) ~VectorInfo() element(i: Integer): Integer getSize(): Integer VectorIterInfo index: Integer VectorIterInfo(v: Vector) next(): Integer hasNext(): Boolean Vector *
16
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 getSize()); }
17
VectorIterInfo Example Vector a = new VectorInfo(15); VectorIter iter = new VectorIterInfo(a) ; while ( iter->hasNext() ) cout next() ; cout << endl; Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
18
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:
19
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
20
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); };
21
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.
22
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 an appropriate catch clause.
23
Output 0 14 1 13 2 12 3 11 4 10 5 9 6 8 Middle value is 7
24
Application: quickSort 1010 7 1616 49 1818 -38 1212 4789 1010 1212 1616 1818 Input: Output: Constraints: Perform the sort ``in place'' (no other memory is used)
25
quickSort Trace 1010 7 1616 49 comparison element from to 1818 -38 1212
26
quickSort Trace (cont'd) 1010 7 1616 49 comparison element from to 1818 -38 1212 1818 1616 1212 784 1010 9 partition everything less than comparison element everything greater than or equal to comparison element
27
quickSort Trace (cont'd) 1010 7 1616 49 comparison element from to 1818 -38 1212 1818 1616 1212 784 1010 9 partition -37849 partition 1616 1212 1818 everything less than comparison element everything greater than or equal to comparison element
28
quickSort Trace (cont'd) 1010 7 1616 49 comparison element from to 1818 -38 1212 1818 1616 1212 784 1010 9 partition -37849 partition 4 789 1616 1212 1818 1212 1616 swap partition everything less than comparison element everything greater than or equal to comparison element
29
quickSort Trace (cont'd) 1010 7 1616 49 comparison element from to 1818 -38 1212 1818 1616 1212 784 1010 9 partition -37849 partition 4 789 1616 1212 1818 1212 1616 swap -34789 1010 1212 1616 1818 partition everything less than comparison element everything greater than or equal to comparison element final sorted vector
30
The partition Procedure 1010 7 1616 49 comparison element from to 1818 -38 1212 1010 7 1616 49 1818 8 1212 iterate up until out-of-place element found: 1010 7 1616 49 1818 -38 1212 iterate down until out-of-place element found: 1010 7849 1818 -3 1616 1212 swap: 1010 7849-3 1818 1616 1212 repeat: -37849 1010 1818 1616 1212 swap comparison element with appropriate element:
31
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); };
32
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();
33
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
34
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
35
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); }
36
SortInfo::Partition Method Integer 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() getIndex()) { // Search forward while ((front->getIndex() getIndex()) &&(compare > front->getItem())) front->next(); // Search backward while ((front->getIndex() getIndex()) &&(compare getItem())) back->previous(); // Exchange items swap(front->getItem(), back->getItem()); }...
37
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); }
38
Analysis of quickSort We will count the number of data movements that quickSort does. To do this we will use a recursion tree. We start with the original vector as root: 0 N-1
39
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)
40
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)
41
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
42
Assuming Vector Values are Randomly Distributed 0 N-1 Q: What is the height of this tree?
43
Assuming Vector Values are Randomly Distributed (cont'd) N Levels 2 1 4 2 8 3 16 4... N log 2 N
44
Assuming Vector is Already Sorted or Nearly Sorted 0 N-1......... Q: What is the height of this tree? A: N
45
Analysis of quickSort (Summary) ● The total number of data movements done by quickSort is: – O(Nlog(N)) if vector values are randomly distributed – O(N 2 ) 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
46
Efficiency Comparisons 0 N O(N) array implementation of priority queue O(logN) binary heap implementation of priority queue O(b N ) minimaxValue time O(NlogN) quicksort O(N 2 ) bubblesort
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.