You are on page 1of 16

C++ STL Algorithms

• Generic algorithms
– Apply to a wide range of types
• E.g., sorting integers (long) or intervals (long, long)

– Don’t require inheritance relationships
• Types substituted need not have a common base class • Need only to be models of the algorithm’s concept

• Implementations in C++
– Rely on templates, interface-based polymorphism – Algorithms are implemented as function templates – Use types that model iterator concepts – Iterators in turn give access to containers
CSE 332: C++ STL algorithms

return *s == c ? s : (char *) 0. char c) { while (*s != 0 && *s != c) ++s.Example: Linear Search • From Austern: “Generic Programming and the STL” • Sequential (linear) search: find char c in string s char *strchr (char* s. } • Problem: not very general – “Range” of iteration is always defined up to ‘\0’ character – Only works for a “zero terminated” string in C/C++ CSE 332: C++ STL algorithms .

} •Gives an explicit range (calculate its length – how?) •Assumes first is before last (can check – how?) •Note how caller checks for success changed: why? CSE 332: C++ STL algorithms . 11): use a range char *find1(char* first.Linear Search with Ranges •First generalization (Austern. pp. char* last. char c){ while (first != last && *first != c) ++first. return first.

General Requirements for Linear Search • Before we try to improve the algorithm further –Let’s come up with a definition of what it needs to do –This helps to plan what to require and what to leave flexible • Any linear search implementation must offer a way to: 1.Detect the end of the sequence 5.Represent a position within the sequence 3.Return a value as an indication of success or failure • Goal: meet these requirements flexibly and efficiently CSE 332: C++ STL algorithms .Advance to the next element of the sequence 4.Indicate the sequence over which search will occur 2.

return first.Linear Search over Parameterized Types • Second generalization: use templates to parameterize the function argument types template <typename T> T *find2(T *first. 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 data structure whose ranges can’t be traversed via simple pointers? CSE 332: C++ STL algorithms . T *last.

} • Our first generic algorithm – Searches any one-dimensional sequence of elements • Notice we did not throw an exception – “Not found” is a normal result. Iterator last. not an aberration CSE 332: C++ STL algorithms . 13): template <class Iterator. class T> Iterator find(Iterator first.Linear Search with Generic Iterators • Third generalization: separate iterator type parameter • The STL’s linear search algorithm (Austern pp. return first. const T& value) { while (first != last && *first != value) ++first.

g.g. we couldn’t use a linked list iterator in find1 or even find2 • Any specific type that meets the requirements is a model of that concept – E. array iterators) • No inheritance-based relationship between them • But both model iterator concept necessary for find CSE 332: C++ STL algorithms .g.Algorithm Concepts and Models • Remember a concept gives a set of type requirements – Classify/categorize types (e. list<int>::iterator vs.. random access iterators) – Tells whether or not a type can or cannot be used with a particular STL algorithm (get a compiler error if it cannot) • E.. char * in find • Different abstractions (bi-linked list vs..

class T> Iterator find (Iterator first. Continued • What very basic concept does the last statement in STL find.Concepts and Modeling.) assume? – Asked another way. return first. } CSE 332: C++ STL algorithms . (return first. Iterator last. const T & value) { while (first != last && *first != value) ++first. what must be able to happen to first when it’s returned from function find? – Same requirement imposed by by-value iterator parameters • What other capabilities are required of the Iterator and T type parameters by the STL find algorithm ? template <class Iterator.

Matching an Algorithm to the Iterators it Needs Category Read Access Write Iteration Comparison Output Input Forward Bidirectional Random Access =*p -> [] *p= ++ -.+ .+= -= == != < > <= >= =*p =*p =*p -> -> -> *p= *p= *p= ++ ++ ++ ++ -- == != == != == != What STL iterator category does find require? CSE 332: C++ STL algorithms .

especially used with vector<T> • Examples include accumulate. random_shuffle – Sorting and related operations • Modify the order in which elements appear in a sequence • Examples include sort. count_if – Mutating sequence operations • Modify the order or values of the sequence elements • Examples include copy. next_permutation • The <numeric> header file contains – General numeric operations • Scalar and matrix algebra.Organization of Algorithms within the STL • The <algorithm> header file contains – Non-modifying sequence operations • Do some calculation but don’t change sequence itself • Examples include count. inner_product CSE 332: C++ STL algorithms .

i) << " times in v" << endl. v. char * []) { vector<int> v. int i = cout << << << 7.Example of Using Non-Modifying Algorithms • count algorithm – Moves through iterator range – Checks each position for equality – Increases count if equal #include <iostream> #include <vector> #include <algorithm> using namespace std. int main (int.push_back(1). return 0.push_back(2). /* output is 7 appears 0 times in v 2 appears 2 times in v */ i = 2. v. } CSE 332: C++ STL algorithms .end().end(). cout << i << " appears “ << count(v.push_back(3). v.begin(). i) " times in v" << endl. v. v.begin(). v.push_back(2). i << " appears “ count(v.

increases count #include <iostream> #include <vector> #include <algorithm> using namespace std. char * []) { vector<int> v. odd<int>()) << " odd numbers in v" << endl. } /* output is there are 2 odd numbers in v */ CSE 332: C++ STL algorithms .Using a Function Object to Extend an Algorithm • count_if algorithm – Generalizes the count algorithm – Instead of comparing for equality to a value – Applies a given predicate function object (functor) – If functor’s result is true. v. int main (int.push_back(2). v. v. return 0. template <typename T> struct odd { bool operator() (T t) const { return (t % 2) != 0.push_back(2). cout << "there are " << count_if(v.begin(). v. v.end(). } }.push_back(3).push_back(1).

int main (int argc. ifstream input_file (input_file_name./copytest Makefile Makefile2 copied input file: Makefile to output file: Makefile2 cdgill@hive> diff Makefile Makefile2 cdgill@hive> */ CSE 332: C++ STL algorithms .} string input_file_name (argv[1]). istream_iterator<char>().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. string output_file_name (argv[2]). } /* output: cdgill@hive> . copy (inF.c_str()). istream_iterator<char> inF (input_file). otF). ofstream output_file (output_file_name. char * argv[]) { if (argc != 3) {return 1. cout << << << << "copied input file: " input_file_name << endl " to output file: " output_file_name << endl. return 0. “end-of-file”) input iterator – Note use of noskipws (ensure behavior matches expectations) #include <iostream> #include <string> #include <fstream> #include <iterator> #include <algorithm> using namespace std. input_file >> noskipws.c_str()). ostream_iterator<char> otF (output_file).

cout << s << " ". s. cout << "sorted: " << s << endl. called a “permutation” – Can use to generate all possible orders of a given sequence /* output is original: asdf sorted: adfs permutations: adsf afds afsd dafs dasf dfas dsfa fads fasd fsad fsda sadf sdfa sfad sfda */ asdf dfsa fdas safd adfs asfd dsaf fdsa sdaf CSE 332: C++ STL algorithms .begin().end()). int main (int. s. cout << "original: " << s << endl. cout << "permutations:" << endl. char * []) { string s = "asdf". cout << endl.begin().Example of Using Sorting Algorithms • sort algorithm – Reorders a given range – Can also plug in a functor to change the ordering function #include <iostream> #include <string> #include <algorithm> using namespace std. return 0.end()). } while (s != t). sort (s. string t(s). do { next_permutation (s. } • next_permutation algorithm – Generates a specific kind of reordering.

return 0. cout << "v contains ". v. int main (int. v. s < v.push_back(2). ++s) { cout << v[s] << " ". cout << "the sum of the elements in v is " << accumulate (v.begin(). v.end(). v.begin().push_back(1).push_back(2).end().begin(). v. char * []) { vector<int> v. } • inner_product algorithm – Computes the inner (also known as “dot”) product of two vectors: sum of the products of their respective elements /* 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 */ CSE 332: C++ STL algorithms . v. 0) << endl. } cout << endl. for (size_t s = 0. cout << "the inner product of v and itself is " << inner_product (v.size().push_back(3). 0) << endl. v.Example of Using Numeric Algorithms • accumulate algorithm – Sums up elements in a range (based on a starting sum value) #include <iostream> #include <vector> #include <numeric> using namespace std.

generic functions – Combine easily with a variety of containers/iterators – Support many common data structure manipulations • Finding and modifying values. re-ordering.Concluding Remarks • STL algorithms give you useful. numeric operations – Reusing them saves you from writing code • Many STL algorithms can be extended – Especially by plugging function objects into them – We’ve looked at how to use a few function objects – Next lecture we’ll look at how function objects work • You can also create your own generic algorithms – If something you need is not in the STL – Think about the iterator and data type concept it requires – Implement it so it works as generically as possible CSE 332: C++ STL algorithms .