TDDD38 APiC++ Standard Library – Algorithms 265 Standard Algorithms Library #include <algorithm> Generic components that programs may use to perform algorithmic operations on e.g. containers. • mainly function templates – most operate on data structures and objects through iterators • categorized as follows in the standard library – non-modifying sequence operations – mutating sequence operations – sorting and related operations – algorithms for numeric computations are found in the Numerics library, <numeric> – C library algorithms, <cstdlib> • separated from the particular implementation of different data structures by iterators – the iterator category names are used to reflect the minimum requirements of an algorithm, e.g. BidirectionalIterator • move semantics may be applied by some algorithms File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 266 Regarding exam • the following algorithms are not an exam topic – shuffle algorithms – set algorithms – heap algorithms – lexicographical comparison algorithms – permutation generators – allowed, if suitable and available and not contradicted by given requirements • important to have a good overview and understanding of the algorithms library – what kind of algorithms available and how to use them – sufficient practice in using algorithms, in combination with other components • cplusplus.com Reference will be available at exam (web browser) • see the course examination page for more information File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 267 Notes on standard algorithms design (1) • many algorithms comes in several versions, sometimes with slightly different names, for example – a basic version and a version taking an additional predicate, named algorithm and algorithm_if copy(begin(v1), end(v1), back_inserter(v2)); copy_if(begin(v1), end(v1), back_inserter(v2), bind(less_equal<int>{}, _1, 10)); – an in-place version and a copy version, named algorithm and algorithm_copy (and possibly algorithm_copy_if) reverse(begin(v), end(v)); reverse_copy(begin(v1), end(v1), back_insert(v2)); – one version for one input range and one version for two input ranges transform(begin(v1), end(v1), begin(v1), negate<int{}); // result in v1 transform(begin(v1), end(v1), begin(v2), back_inserter(v3), plus<int>{}); Note 1: less_equal, negate and plus are standard function object types, bind is a utility function for binding function arguments Note 2: a lambda expression is much simpler to use instead of bind and less_equal File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 268 Notes on standard algorithm design (2) • some algorithms does not modify size, as one might expect, but instead leave “garbage” at the end of the modified range unique(begin(v), end(v)); template<typename ForwardIterator> ForwardIterator unique(ForwardIterator first, ForwardIterator last) { // Skip to first occurrence of adjacent equal values first = std::adjacent_find(first, last); if (first == last) return last; 1 2 3 3 4 5 5 5 6 first last // Uniquify the rest ForwardIterator dest = first; ++first; while (++first != last) if (! (*dest == *first)) *++dest = std::move(*first); return ++dest; 1 2 3 4 5 6 5 dest first 5 6 last } • to get rid of the “garbage” it also must be erased (size adjusted) v.erase(unique(begin(v), end(v)), end(v)); File: Standard-Algorithms-OH-en 1 2 3 4 5 6 © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 269 Notes on standard algorithm design (3) • functions (function pointers or function objects) are passed and returned by value template <typename InputIterator, typename Function> Function for_each(InputIterator first, InputIterator last, Function f) { for ( ; first != last; ++first) f(*first); return std::move(f); } – the return value from the function f, if any, is ignored – f typically have a side effect, e.g. to print the element – classified as non-modifying, since it does not explicitly modify the elements, but… void negate(int& i) { i = -i; } // reference parameter for_each(begin(v), end(v), negate); // the elements in v are negated – the fact that for_each returns f opens for interesting possibilities – f can be a function object with state Fun_Obj fun; fun = for_each(begin(v), end(v), fun); cout << fun.get_result() << endl; – or use a std::reference_wrapper to pass fun by reference – example later File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 270 Notes on standard algorithm design (4) • ordinary function call syntax is always used within the algorithms template<typename ForwardIterator, typename Generator> void generate(ForwardIterator first, ForwardIterator last, Generator gen) { for (; first != last; ++first) *first = gen(); } – to call a member function, a function call wrapper must be used (covered in Function objects) File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 271 Notes on standard algorithm design (4) • assignment (operator=) is used for copying elements template<typename InputIterator, typename OutputIterator> OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result) { for ( ; first != last; ++result, ++first) *result = *first; return result; } – if the capacity of result is not guaranteed an insert iterator must be used copy(begin(v1), end(v1), back_inserter(v2)); • operator== and operator< are used by default when comparing elements for equality or for ordering – such algorithms typically come in two versions, one using the default implicitly and one taking a comparer as an extra argument sort(begin(v1), end(v1)); // uses operator< sort(begin(v1), end(v1), std::greater<int>{}); sort(begin(v1), end(v1), [](int x, int y){ return y < x; }); File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 272 Notes on standard algorithm design (5) • iterators are passed by value template <typename InputIterator, typename OutputIterator, typename Predicate> OutputIterator copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred) { for (; first != last; ++first) if (pred(*first)) { *result = *first; ++result; } return result; } – semantically the objects are accessed by reference • input and output ranges may or may not overlap – ranges may not overlap for (most) copy, swap and set algorithms • iterators can be invalidated by algorithms – modifying algorithms typically invalidate stored iterators File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 273 Notes on standard algorithm design (6) • input values of generic type are passed by const&, and return values are returned by const&, when suitable template <typename T> const T& min(const T& a, const T& b) { if (b < a) return b; return a; } – semantically this is passing by value in a effective way, and reduces the requirements on T (no copy/destroy required) • input values of (to be) simple type are passed by value template <typename InputIterator, typename Size, typename OutputIterator> OutputIterator copy_n(InputIterator first, Size n, OutputIterator result) { for ( ; n > 0; --n) { *result = *first; ++first; ++result; } return result; } File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 274 reference_wrapper Utility class to create objects that act as references but can be copied. • two helper functions – ref(T) returns a T& wrapper object – cref(T) returns a const T& wrapper object Example: class sum { public: sum() : acc(0) {} void operator()(int x) { acc += x; } int get_sum() const { return acc; } private: int acc; }; • algorithm for_each takes a function as third argument and passes it by value, and finally return that copy by value vector<int> v{ 1, 2, 3, 4, 5, 6, 7, 8, 9 }; sum s; for_each(begin(v), end(v), ref(s)); // alternative: s = for_each(begin(v), end(v), s); cout << s.get_sum() << endl; File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 275 Non-modifying sequence operations (1) Function for_each(first, last, f) applies the function f to each element in [first, last); returns f Note: f can be passed by reference using std::reference_wrapper n count(first, last, value) returns the number of elements in [first, last) equal to value n count_if(first, last, pred) returns the number of elements in [first, last) for which pred is true iter find(first, last, value) find the first element in [first, last) equal to value iter find_if(first, last, pred) find the first element in [first, last) for which pred is true iter find_if_not(first, last, pred) find the first element in [first, last) for which pred is false iter find_first_of(first1, last1, first2, last2) find the first element in [first1, last1) equal to one of the elements in [first2, last2) iter find_end(first1, last1, first2, last2) find the last subsequence in [first1, last1) equal to [first2, last2) iter search(first1, last1, first2, last2) search for the first subsequence in [first1, last1) equal to [first2, last2) iter search_n(first, last, count, value) search for the first subsequence in [first, last) of count elements equal to value Note 1: algorithms returning an iterator returns last/last1 if not successful. Note 2: find_first_of, find_end, search and search_n use operator== by default to compare for equality; they all also come in a version taking a binary predicate to be used instead. File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 276 Non-modifying sequence operations (2) bool all_of(first1, last1, pred) true if pred is true for all elements in [first1, last1) bool any_of(first1, last1, pred) true if pred is true for any element in [first1, last1) bool non_of(first1, last1, pred) true if pred is true for none of the element in [first1, last1) iter adjacent_find(first, last) returns iterator to first two consecutive equal elements in [first, last), or last bool equal(first1, last1, first2) true if the elements in [first1, last1) and [first2, …) are equal pair<it1, it2> mismatch(first1, last1, first2) returns the positions in [first1, last1) and [first2, …) where the elements in the sequences differ for the first time; if all elements match, last1 and an iterator into first2 offset by the size of [first1, last1) is returned bool is_permutation(first1, last1, first2) true if there is a permutation of the elements in [first2,…) with the same number of elements as are in [first1, last1) and for which the elements in the permutation and in [first1, last1) are equal Note: adjacent_find, equal, mismatch, and is_permutation by default uses operator== for equality test, They all also come in a version taking a binary predicate to be used instead. File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 277 Mutating sequence operations (1) fill(first, last, value) assign value to the elements in [first, last) fill_n(first, n, value) assign value to the elements in [first, first + n) generate(first, last, gen) invokes gen() and assign the return value to each element in [first, last) generate_n(first, n, gen) invokes gen() and assign the return value to each element in [first, first + n) iter transform(first, last, result, unary-op) applies unary-op to the elements in [first, last), assigns result to [result, …) iter transform(first1, last1, first2, result, binary-op) applies binary-op to the elements in two ranges, assigns result to [result, …) iter copy(first, last, result) copies all elements from [first, last) into [result, …) iter copy_n(first, n, result) copies the first n elements from [first, …) into [result, …) iter copy_if(first, last, result, pred) copies all elements in [first, last) for which pred is true iter copy_backward(first, last, result) copies elements backwards from [first, last) into [result, …) iter move(first, last, result) like copy but elements are moved iter move_backward(first, last, result) like copy_backward but elements are moved swap(x, y) exchanges values in two locations x and y iter swap_ranges(first1, last1, first2) exchanges values pair-wise in two ranges [first1, last1) and [first2, …) iter_swap(it1, it2) exchanges values pointed to by iterators it1 and it2 File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 278 Mutating sequence operations (2) replace(first, last, old, new) substitutes each element in [first, last) equal to old with new replace_if(first, last, pred, new) substitutes each element in [first, last) for which pred is true with new iter replace_copy(first, last, result, old, new) as replace, but the result is copied into another range [result, …) iter replace_copy_if(first, last, result, pred, new) as replace_if, but the result is copied into another range [result, …) iter remove(first, last, value) eliminates all elements in [first, last) equal to value iter remove_if(first, last, pred) eliminates all elements in [first, last) for which pred is true iter remove_copy(first, last, result, value) as remove but the result is copied into [result, …) iter remove_copy_if(first, last, result, pred) as remove_if but the result is copied into [result, …) iter unique(first, last) eliminates all but the first from every consecutive group of equal elements iter unique_copy(first, last, result) as unique but the result is copied into [result, …) reverse(first, last) reverses the order of the elements in [first, last) iter reverse_copy(first, last, result) as reverse but the result is copied into [result, …) rotate(first, new-first, last) left rotate the elements in [first, last) so new-first becomes the first element iter rotate_copy(first, new-first, last, result) as rotate but the result is copied into [result, …) Note 1: iter returned by the functions above, is an iterator pointing past-the-end of the resulting range. Note 2: the input range for unique and unique_copy is normally supposed to be sorted. Note 3: unique and unique_copy also comes in a version taking a predicate, to be used instead of operator== to compare for equality. File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 279 Mutating sequence operations (3) random_shuffle(first, last) shuffles the elements in [first, last) in a random way; deprecated in C++14, use shuffle! random_shuffle(first, last, rand) as random_shuffle but using function rand; deprecated in C++14, use shuffle! shuffle(first, last, uniform-rand) shuffles the elements in [first, last) in a random way using function uniformrand iter partition(first, last, pred) places all element in [first, last) satisfying pred before elements not satisfying pred; iter points at the first element in the second part iter stable_partition(first, last, pred) as partition but the relative order of elements in both groups is preserved bool is_partitioned(first, last, pred) true if [first, last) is empty, or if [first, last) is partitioned by pred, i.e. all elements satisfying pred occurs before those that do not iter partition_point(first, last, pred) [first, last) shall be partitioned by pred, i.e. all elements that satisfy pred shall appear before those that do not; returns an iterator referring to the partition point pair partition_copy(first, last, out-true, out-false, pred) copies elements in [first, last) satisfying pred to out-true, elements not satisfying pred to out-false; returns pair such that first is the end of the output range beginning at out-true and second is the end of the output range beginning at out-false File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 280 Sorting and related operations (1) sort(first, last) sorts the elements in [first, last) stable_sort(first, last) as sort but preserving the relative order of equal elements partial_sort(first, middle, last) places the lowest-valued (middle - first) elements in [first, last) sorted in [first, middle) iter partial_sort_copy(first, last, result, result-last) places the min(last - first, result-last - result) lowest-valued elements from [first, last) sorted in result in [result, result-last); iter is past-the-end of result nth_element(first, nth, last) nth must be an iterator pointing to an element in [first, last); after nth_element the element in the nth position is the element that would be there if the whole range was sorted; elements to the left of nth are less or equal to the nth element, elements to the right of nth are greater or equal, but not ordered in any other way bool is_sorted(first, last) returns true is all elements in [first, last) is sorted, false otherwise iter is_sorted_until(first, last) returns the last iterator in [first, last) for which [first, iter) is sorted Note 1: operator< is used by default to compare; all also have a version taking a comparer to be used instead. Note 2: from sort/stable_sort and down to nth_element, the degree of sorting is decreasing. Note 3: library guarantee that sort moves (not copies), if available. File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 281 Sorting and related operations (2) bool binary_search(first, last, value) returns true if value is found in [first, last) iter lower_bound(first, last, value) returns first position where value can be inserted without violating the ordering iter upper_bound(first, last, value) returns last position where value can be inserted without violating the ordering pair<it1, it2> equal_range(first, last, value) returns the largest subrange [it1, it2) where value can be inserted without violating the ordering; the two iterators returned corresponds to the ones returned by lower_bound and upper_bound. Note 1: operator< is used by default to compare; all also have a version taking a comparer, to be used instead, as last argument. Note 2: binary_search works for both random access an forward iterators. iter merge(first1, last1, first2, last2, result) merges two sorted ranges, [first1, last1) and [first2, last2) into one sorted range, [result, …); iter is past-the-end of the resulting range inplace_merge(first, middle, last) merges two sorted consecutive ranges, [first, middle) and [middle, last), putting the result into [first, last) Note 1: operator< is used by default to compare; both also have a version taking a comparer to be used instead. Note 2: merging is stable, i.e. elements from the first range comes before equivalent elements from the second range. File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 282 Set algorithms Works on sorted structures, also works on multiset. bool includes(first1, last1, first2, last2) true if every element in [first2, last2) is contained in [first1, last1) iter set_union(first1, last1, first2, last2, result) constructs a sorted union in [result, …) of the elements from the two ranges [first1, last1) and [first2, last2) iter set_intersection(first1, last1, first2, last2, result) constructs a sorted intersection in [result, …) of the elements from the two ranges [first1, last1) and [first2, last2) iter set_difference(first1, last1, first2, last2, result) copies the elements of range [first1, last1) which are not present in [first2, last2) to [result, …) iter set_symmetric_difference(first1, last1, first2, last2, result) copies the elements of range [first1, last1) not present in [first2, last2) and elements of range [first2, last2) not present in range [first1, last1) to the range [result, …) Note 1: operator< is used by default to compare; all also have a version taking a comparer to be used instead. Note 2: the iterator returned by the functions above refers to the end of the constructed range (result). File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 283 Heap algorithms make_heap(first, last) constructs a heap (max-heap) out of the range [first, last) push_heap(first, last) the range [first, last -1) must be a valid heap; the value to push must first be placed in location last-1; places the value in location last-1 into the resulting heap [first, last) pop_heap(first, last) the range [first, last) must be a valid heap; swaps the value in location first with the value in location last-1 and makes [first, last -1) into a heap sort_heap(first, last) sorts the elements in the heap [first, last); the range [first, last) is thereafter not a heap; not stable bool is_heap(first, last) returns true if the elements in [first, last) are heap ordered, otherwise false iter is_heap_until(first, last) returns the last iterator in [first, last) for which the range [first, iter) is heap ordered, otherwise last Note 1: operator< is used by default to compare; all also have a version taking a comparer to be used instead. Note 2: make_heap(), push_heap(), and pop_heap() are used in the implementation of priority_queue. Example: vector<int> v{ 8, 1, 4, 6, 5, 8, 3, 2, 7, 9 }; make_heap(begin(v), end(v)); // 9 8 8 7 5 4 3 2 6 1 v.push_back(10); push_heap(begin(v), end(v)); // 9 8 8 7 5 4 3 2 6 1 10 // 10 9 8 7 8 4 3 2 6 1 5 pop_heap(begin(v), end(v)); // 9 8 8 7 5 4 3 2 6 1 10 File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 284 Minimum and maximum operations value min(a, b) returns the smaller value of a and b, a when a and b are equivalent value min(initializer-list) returns the (leftmost) smallest value in initializer-list value max(a, b) returns the larger value of a and b, a when a and b are equivalent value max(initializer-list) returns the (rightmost) largest value in initializer-list pair minmax(a, b) returns a pair with smallest of a and b first pair minmax(initializer-list) returns a pair with (leftmost) smallest and (rightmost) largest in initializer-list iter min_element(first, last) returns iterator to the (leftmost) smallest element in [first, last) iter max_element(first, last) returns an iterator to the largest element in [first, last); if several equivalently large elements, an iterator to the first of those pair minmax_element(first, last) returns a pair with iterators to the leftmost) smallest and the (rightmost) largest element in the range [first, last) Note: operator< is used by default to compare; all also have a version taking a comparer to be used instead. File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 285 Lexicographical comparison bool lexicographical_compare(first1, last1, first2, last2) returns true if the elements in [first1, last1) are lexicographically less than the elements in [first2, last2) Note: operator< is used by default to compare; there is also a version taking a comparer to be used instead. Lexicographical comparison means • if two sequences have the same number of elements and their corresponding elements are equivalent then neither sequence is lexicographically less than the other abcd1 < abcd2 not true abcd2 > abcd1 not true • if one sequence is a prefix of the other, then the shorter sequence is lexicographically less than the longer sequence abc < abcde true • otherwise the lexicographical comparison of two sequences yield the same result as the comparison of the first pair of elements that are not equivalent abcde < abcxe File: Standard-Algorithms-OH-en true, because d < x © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 286 Permutation generators bool next_permutation(first, last) takes the sequence [first, last) and transforms it to the next permutation; returns true if such a permutation exists, otherwise false bool prev_permutation(first, last) takes the sequence [first, last) and transforms it to the previous permutation; returns true if such a permutation exists, otherwise false Note: operator< is used by default to compare; both also have a version taking a comparer, to be used instead • the next permutation is found by assuming that the set of all permutations are sorted with respect to operator<, or to a given comparer. abc < acb < bac < bca < cab < cba File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet TDDD38 APiC++ Standard Library – Algorithms 287 Numeric algorithms #include <numeric> T accumulate(first, last, init) initializes an accumulator with init, adds each value in [first, last) to the accumulator using operator+; returns accumulator value T inner_product(first1, last1, first2, init) initializes an accumulator with init; multiplies each pair of elements in [first1, last1) and [first2,…) with each other and adds the result to the accumulator using operator+; returns accumulator value iter partial_sum(first, last, result) assigns to every element in [result, …) the corresponding partial sum; (*first), (*first + *(first+1)), (*first + *(first+1) + *(first+2)), …, using operator+; returns past-the-end iterator for the resulting range iter adjacent_difference(first, last, result) the first element in result is assigned to the first value in [first, last); each element in [result+1,…) is assigned to the difference between the corresponding value in [first+1, last) and its previous value; returns past-the-end iterator for the resulting range. iota(first, last, value) assigns all elements in [first, last) increasing values starting with value Note 1: accumulate, inner_product, and partial_sum also have a version taking a binary operation to be used instead of operator+ Note 2: adjacent_difference also have a version taking a binary operation to be used instead of operatorThe Numerics library also have support for complex numbers, random number generation, numeric arrays, and C99 standard library functionality. File: Standard-Algorithms-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet