Transcript ppt

The C++ Algorithm Libraries

• A standard collection of generic algorithms

– Applicable to various types and containers • •

E.g.

, sorting integers (

int

) vs. intervals (

pair

)

E.g.

, sorting elements in a

vector

vs. in a C-style array – Polymorphic even without inheritance relationships • Types substituted need not have a common base class • Must only provide the operators the algorithm needs

• Significantly used with the sequence containers

– To reorder elements within a container’s sequence – To store/fetch values into/from a container – To calculate various values and properties from it CSE 332: C++ Algorithms I

Motivating Example: Searching a String

• From Austern: “ Generic Programming and the STL ” • Sequential (linear) search: find

char c

in

string s char * strchr (char* s, char c) { while (*s != 0 && *s != c){ ++s; } return *s == c ? s : (char *) 0; }

• Problem: not very general – “ Range ” of iteration is always defined up to ‘ \0 ’ – Only works for a “ zero terminated ” character string in C/C++ CSE 332: C++ Algorithms I

Improving Linear Search with Ranges

• First generalization (Austern, pp. 11): use a

range (something that sequential containers can give us!)

char * find1 (char* first, char* last, char c){ while ( first != last && * first != c) ++first ; return first; }

• Gives an explicit range (calculate its length – • Assumes first is before last (can check – how?) how?) • Note how caller checks for success changed: why?

CSE 332: C++ Algorithms I

Linear Search over Parameterized Types

• Second generalization: use templates to parameterize the function argument types

template T * find2( T * first, T return first; * last, const T & value){ while (first != last && *first != value) ++first; }

• How much did the

find1

code need to change?

• One last problem – What if we want to apply this to a container (e.g.,

list

) whose range can’t be traversed via simple pointers?

CSE 332: C++ Algorithms I

Linear Search with Generic Iterators

• Third generalization: separate iterator type parameter • We arrive at the

find

algorithm (Austern pp. 13):

template < typename Iterator, Iterator find ( Iterator typename T> first, Iterator last, } ++first; return first; const T & value) { while (first != last && *first != value)

• Notice how algorithm depends on the iterators • Notice how refinements made algorithm more abstract – … but still essentially does the same thing – i.e., algorithm structure (and time complexity) is the same CSE 332: C++ Algorithms I

Organization of C++ Algorithm Libraries

• The

header file contains – Non-modifying sequence operations • Do some calculation but don’t change sequence itself • Examples include

count

,

count_if

– Mutating sequence operations • Modify the order or values of the sequence elements • Examples include

copy

,

random_shuffle

– Sorting and related operations • Modify the order in which elements appear in a sequence • Examples include

sort

,

next_permutation

• The

header file contains – General numeric operations • Scalar and matrix algebra, especially used with vector • Examples include

accumulate

,

inner_product

CSE 332: C++ Algorithms I

Example of Using Non-Modifying Algorithms

count

algorithm – Moves through iterator range – Checks each position for equality – Increases count if equal

#include #include #include using namespace std; int main (int, char * []) { vector v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(2); /* output is 7 appears 0 times in v 2 appears 2 times in v */ int i = 7; cout << i << " appears " << count(v.begin(), v.end(), i) << " times in v" << endl; i = 2; cout << i << " appears " << count(v.begin(), v.end(), i) << " times in v" << endl; } return 0;

CSE 332: C++ Algorithms I

Example of Using Mutating Algorithms

copy

algorithm – Copies from an input iterator range into an output iterator – Note use of default constructor to get an “off-the-end” (here, “end-of-file”) input iterator – Note use of noskipws (need to make sure container behavior matches what you want to do)

ifstream input_file (input_file_name.c_str()); ofstream output_file (output_file_name.c_str()); input_file >> noskipws; istream_iterator i (input_file); ostream_iterator o (output_file); copy (i, istream_iterator(), o); #include #include #include #include cout << "copied input file: " << input_file_name << endl << " to output file: " << output_file_name << endl; #include return 0; using namespace std; } int main (int argc, char * argv[]) { if (argc != 3) {return 1;} string input_file_name (argv[1]); string output_file_name (argv[2]); /* output: cdgill@hive> ./copytest Makefile Makefile2 copied input file: Makefile to output file: Makefile2 cdgill@hive> diff Makefile Makefile2 cdgill@hive> */

CSE 332: C++ Algorithms I

• •

Example of Using Sorting Algorithms

sort

algorithm – Reorders a given range – Can also plug in a functor to change the ordering function

next_permutation

algorithm – Generates a specific kind of reordering, called a “permutation” – Can use to generate all possible orders of a given sequence

#include #include #include using namespace std; int main (int, char * []) { string s = "asdf"; cout << "original: " << s << endl; sort (s.begin(), s.end()); cout << "sorted: " << s << endl; string t (s); cout << "permutations:" << endl; /* output is original: asdf sorted: adfs permutations: adsf afds afsd asdf asfd dafs dasf dfas dfsa dsaf dsfa fads fasd fdas fdsa fsad fsda sadf safd sdaf sdfa sfad sfda adfs */ do { next_permutation (s.begin(), s.end()); cout << s << " "; } while (s != t); cout << endl; return 0; }

CSE 332: C++ Algorithms I

• •

Example of Using Numeric Algorithms

accumulate

algorithm – Sums up elements in a range (based on a starting sum value)

inner_product

algorithm – Computes the inner (also known as “dot”) product of two matrixes: sum of the products of their respective elements

#include #include #include using namespace std; int main (int, char * []) { vector v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(2); /* output is: v contains 1 2 3 2 the sum of the elements in v is 8 the inner product of v and itself is 18 */ cout << "v contains "; for (size_t s = 0; s < v.size(); ++s) { cout << v[s] << " "; } cout << endl; cout << "the sum of the elements in v is " << accumulate (v.begin(), v.end(), 0) << endl; cout << "the inner product of v and itself is " << inner_product (v.begin(), v.end(), v.begin(), 0) << endl; return 0; }

CSE 332: C++ Algorithms I

Concluding Remarks

• C++ libraries give you useful, generic algorithms – Combine easily with a variety of containers/iterators – Support many common data structure manipulations • Finding and modifying values, re-ordering, numeric operations – Reusing them saves you from writing code • Many STL algorithms can be extended further – Especially by plugging functors into them – Next time we’ll look at how functors work, and how to use them, as well as at algorithms and iterators in more detail CSE 332: C++ Algorithms I