stl algorithms algorithms independent of containers
TRANSCRIPT
STL Algorithms
algorithms independent of containers
STL Algorithms Description• independent of container types: operate on iterators
– operate on half-open range of elements of a container specified by iterators• often behavior can be modified through callbacks – references to code• callbacks
– function pointers (C-style)– function objects (functors)– lambda expressions (C++11)
• most algorithms are declared in <algorithm>, some are in <numeric>
2
Algorithm Example: find• looks for specific element in range• needs <algorithm>• find(beginRange, endRange, toFind)• returns iterator to first matching element in range of the container
– if associative – not necessarily first, use lower_bound• if not found – returns endRange (past last element)• linear complexity
find() method in map and set is faster (logarithmic), use it instead
find() method in list should be used instead
3
find_if with Function Pointer Callback• find_if(beginRange, endRange, condition)• returns iterator to first element in range satisfying condition• third parameter is a callback• may be the name of a function (function pointer)
– need to accept element type– need to be a predicate (return boolean)
• example:
vector<int> vect;
…
auto it=find_if(vect.begin(), vect.end(), moreThan5);
…
bool moreThan5(int elem){
return elem>5;
}
4
Lambda Expressions• anonymous function
• defined in C++11
• syntax: [capture] -> returnType (parameters){body}• capture – passing discipline and (optionally) name of variables taken from
outside of scope of the lambda expressions– [] no variables defined. Attempting to use any external variables in the
lambda is an error
• clang/gcc apparently still capture external variables, it is not standard– [x, &y] x is captured by value, y is captured by reference – [&] any external variable is implicitly captured by reference – [=] any external variable is implicitly captured by value
• compiler may be able to deduce return type from return statement: returnType is optional
• if no parameters, parentheses are optional
• example: []{cout << ”Hello, World!” << endl;} • can be assigned to function pointer variables
– watch out for implicit captures
• can be used as parameters for other functions, have to conform to signature5
count_if, generate, for_each• count_if – counts number of elements that satisfy callback condition
int num=55;
int cnt = count_if(vect.begin(), vect.end(), [num](int i){return i==num;});
• generate – fills elements with value returned by callback
generate(vect.begin(), vect.end(), []{return rand()%10;});
• for_each – executes callback for each element
for_each(vect.begin(), vect.end(),
[](int i){cout << i << " ";});
6
accumulate with various callbacks• accumulates data about container• two forms
accumulate(beginRange, endRange, initialValue) – sums elements, sum initialized to initialValue, returns accumulated value
accumulate(beginRange, endRange, initialValue, callback) invokes callback with two arguments, first is accumulator
• callback can be function or lambda
int product(int num1, int num2){
return num1 * num2;
}
double mult = accumulate(vect.begin(), vect.end(), 1, product);
or
double multLambda = accumulate(vect.begin(), vect.end(), 1,
[](int num1, int num2){return num1 * num2;});
7
Function Objects (Functors)• can overload function call operator: operator() in a class
– such class is functor– may have any number of arguments and return any value
• then invoke like a standalone function
class MyFunctor{
public:
MyFunctor(int x) : x_(x) {}
int operator() (int y) {return x_+y;}
private:
int x_;
};
…
MyFunctor addOne(1); // creating a functor object
cout << addOne(2) << endl; // call it like a regular function
• may keep state between calls. Do not use this feature for algorithms!• for simple tasks lambda functions are preferred
8
Predefined Functors, Arithmetic
• STL provides a number of predefined functors• defined in <functional>• in std namespace (need to be imported or scope resolved)• arithmetic: plus, minus, multiplies, divides, modulus• have to be instantiated with type
plus<int> myPlus;
int result = myPlus(3,4);
cut << result << endl;• may be used in algorithms as callbacks
int sum = accumulate(vect.begin(), vect.end(), 0, plus<int>());• regular operators cannot be used as callbacks, functors are adapters that wrap regular
arithmetic operators
9
Comparison and Logical Functors
• comparison functors: equal_to not_equal_to less greater less_equal greater_equal– less is used as default comparison in priority_queue container adapter– may be changed, have to specify container, usually vector– example: reversing sorting order in priority_queue
priority_queue<string, std::vector<string>,std::greater<string>> workWeekR;
• logical functors: logical_and logical_or logical_not – example: logical_and in accumulate to determine if all boolean elements are true
vector<bool> flags;
…
bool allTrue=accumulate(flags.begin(), flags.end(), true,
std::logical_and<bool>());
10
Functor Adapters (Binders)• binder (function adapter) – a specialized function that creates a function by assigning
(binding) a value of parameter of another function• bind() a C++11 feature – most flexible binder
newFunctior bind(oldFunctor, arguments)
where– newFunctor – pointer to new functor with bound parameters– oldFunctor – old functor– arguments – arguments to old functor
• free specified as _1 _2, etc defined in std::placeholders namespace• bound
• auto is useful as return type or it gets complicated• examples
auto f1 = bind(myFunc, _1, str); // binds second parameter to string str
auto f2 = bind(myFunc, _2, _1); // swaps parameters
11
Using Binders to Form Callbacks• binders useful in forming callbacks for algorithims inline
using namespace std::placeholders;
bool passingScore(int s, int threshold){
return s>=threshold;
}
...
// biding second argument of function passingScore to 70
auto it=find_if(vect.begin(), vect.end(),
bind(passingScore, _1, 70));
// binding second argument of standard functor greater_equal
auto it = find_if(vect.begin(), vect.end(), bind(std::greater_equal<int>(), _1, 70));
• this example is probably easier to read with lambda, how would you implement it?
12
Containers of Objects• algorithms perform on non-basic types correctly provided that proper operators are
defined– e.g. operator< for sorting, operator== for searching
• common task: invoke a method on each object– suppose myclass declares myfunc() method and container cont holds
elements of myclass
may be accomplished as follows
for_each(cont.begin(), cont.end(), &myclass::myfunc);– if need to pass parameters, use bind()
for_each(cont.begin, cont.end(), bind(&myclass::myfunc, _1, value));
13
Algorithm Categories
• utility – not operating on containers but useful• non-modifying – not updating the container
– search: min_element, max_element, find_fist_of, search, search_n
– comparison: equal, mismatch, liexicographical_compare– operational: for_each– numerical processing: count, count_if, accumulate
• modifying – updating the container• sorting – sorting or (dis)ordering container• set – set functions
14
Utility Algorithms• min, max, minmax, swap• operate on a couple of elements• use operator<• use function templates• examples
int x=1,y=2;
cout << min(x, y); // prints1
cout << max(x, y); // prints 2
swap(x, y); cout<< x << y; // prints 21
auto pair = minmax(x,y);
cout << pair.first << pair.second; // prints 12
• In C++11, utility algorithms operate on initializer lists: max({1,2,3,4,5});
15
Search Algorithms• return iterator to first element found• accept range• by default use opeator== or operator<• find, find_if, find_if_not – already covered• min_element, max_elment – locate element
auto it=min_element(vect.begin(), vect.end());• adjacent_find – finds the first pair of matching consecutive elements• find_first_of – finds first occurrence of elements in target range• search – finds target subsequence• search_n – finds consecutive elements• searches that work on ordered sequences (sorted vector, map, multimap,
set, multiset): binary_search, lower_bound, upper_bound, equal_range
• C++11 functions: find_if_not, minmax_element, all_of, any_of, none_of
16
Comparison and Operational• comparison – compare entire ranges of elements
equal() – returns true if elements in both ranges are equal
mismatch() returns iterator to the first mismatched element
lexicographical_compare() – dictionary order comparison of elements
• operational
for_each() – executes callback on each element of the range: may print a copy of every element, accumulate info about all elements, etc.
17
Modifying Algorithms• usually operate on two ranges: source range and destination (target) range,
ranges may be independent, overlapping or the same (in place operation)• transform() – similar to for_each() expects callback to return a value
to be stored in the target range– variant: has two source ranges, callback accepts two parameters – one
for each source range and stores value for the target range. Can be used to process two containers
• copy() – copies source to target range• copy_if() – copies if callback returns true C++11
– returns iterator past the last element copied – can be used to trim unused after copy elements
• replace() – replaces elements with particular value with a different one• replace_if() – replaces by new value if callback returns true• reverse() – reverses elements in container• move() – moving elements with C++11 move semantics, leaves source
elements in unspecified by valid state• unique() – eliminates consequent duplicates – useful with sorted
containers
18
Remove (and Erase)• remove() – removes elements with specific value• remove_if() – removes if callback returns true• both modifying algorithms• do not erase elements from containers (do not know if whole or full range)
– instead move remaining elements forward– return iterator past last remaining elements
• remove-erase-idiom – get the returned iterator and then use the container’s erase() function to eliminate removed elements
– can be done in single line• removes are linear
– preferred to iterative erase() invocation – for random access containers memory reorganization to keep continuous, results in quadratic complexity
19
Sorting• sort() – n log(n) sort of the range• merge() – linear merge of source ranges
– target range has to be large enough– does not return iterator; no elements are removed – number of elements
in target container is sum of source sizes: use resize() or erase() to trim target
• unique() – eliminates duplicates, returns iterator past the last element• binary_search() – log(n) search in sorted container for a value, returns
true if found– lower_bound() is same complexity but more useful
• random_shuffle() – reshuffles range in linear time, internally uses rand()
20
Setoperate on sorted containers with unique elements, not necessarily sets; in fact,
sequential containers are recommended• includes() – returns true if first range includes second• set_union() – computes union (duplicates eliminated) from two source
ranges, puts it in destination range, returns pointer past last element• set_intersection() – computes intersection of two source ranges• set_difference() – difference (complement) of first range with second –
elements of first range that are not present in the second• set_symmetric_difference() – elements of first range that are not
present in second and v.v.
21