1 / 27

STL Algorithms

Learn how to use STL algorithms in C++ independently of container types, operating via iterators with callbacks like function pointers, functors, and lambda expressions. Examples included.

cvalencia
Download Presentation

STL Algorithms

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. STL Algorithms algorithms independent of containers

  2. STL Algorithms Description • independent of container types: operate on iterators • operateon the 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>

  3. 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()functionin map and set is faster (logarithmic or constant for hashes), use it instead

  4. 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) • function references exist in C++ as well • 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; }

  5. Lambda Expressions • anonymous function • defined in C++11 • syntax: [capture](parameters) -> returnType {body} • capture – passing discipline and (optionally) name of variables taken from outside of scope (called context) of the lambda expressions • [] no variables defined. Attempting to use any external variables in the lambda is an error • [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 copy (similar to value) variables are captured at the time of lambda definition (not invocation) • if returnTypeis omitted and there is a single return statement in body, compiler deduces return type on basis of return-expression • if no parameters, parentheses are optional • example: []{cout << ”Hello, World!” << endl;} • can be used as parameters for other functions, have to conform to signature

  6. count_if, generate, for_each • count_if– counts number of elements that satisfy callback condition int num=55; intcnt = count_if(vect.begin(), vect.end(), [num](inti){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(), [](inti){cout << i << " ";});

  7. 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;});

  8. Function Objects (Functors) • functor – object that may be invoked as a standalone function • done by overloading operator() may have any number of arguments and return any value class MyFunctor{ public: MyFunctor(int x) : x_(x) {} int operator() (int y) {return x_+y;} private: int x_; }; … • then invoke like a standalone function MyFunctoraddOne(1); // creating a functor object cout << addOne(2) << endl; // call it like a regular function • may keep state between calls. • use this with caution for algorithms as implementations are free to copy/invoke out of order/invoke concurrently • lambdas provide a convenient alternative

  9. generate with Functor class MyFunctor{ public: MyFunctor(int x) : x_(x) {} int operator() () {return x_;} private: int x_; }; … MyFunctoraddIt(5); vector<int> v(10); generate(v.begin(), v.end(), addIt); what are the resultant values of v?

  10. 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

  11. Comparison and Logical Functors • comparison functors: equal_tonot_equal_to less greater less_equalgreater_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_andlogical_orlogical_not • example: logical_and in accumulate to determine if all boolean elements are true vector<bool> flags; … boolallTrue=accumulate(flags.begin(), flags.end(), true, std::logical_and<bool>());

  12. Function 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 newFunction bind(oldFunction, arguments) where • newFuncton – pointer to new function with bound parameters • oldFunction – old function • arguments – arguments to old function, in old-function parameter order • 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

  13. Using Binders to Form Callbacks • binders useful in forming callbacks for algorithims inline using namespace std::placeholders; boolpassingScore(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)); • last example is probably easier to read with lambda, how would you implement it?

  14. std::function • a number of similarly operating constructs: • lambdas (btw, only non-biding lambdas can be assigned to function pointers) • function pointers • functors • binders • std::function allows to point to any of them uniformly • needs functional header • signature is in angle brackets • examples: // lambda function<void(int)> fp = [](int x){cout << x << endl;}; void funcReg(int x){ // regular function cout << x << endl; } function<void(int)> fp = funcReg;

  15. Algorithm Categories • utility – not operating on containers but useful • non-modifying – not updating the container • search: min_element, max_element, find_first_of, search, search_n • comparison: equal, mismatch, lexicographical_compare • operational: for_each • numerical processing: count, count_if, accumulate • modifying – updating the container • sorting – sorting or (dis)ordering container • set – set functions

  16. 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});

  17. Non-ModifyingSearch 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.cbegin(), vect.cend()); • 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

  18. Non-ModifyingComparison 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.

  19. 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 • the target may be one of the source rages • 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 but valid state • may move whole container • unique() – eliminates consequent duplicates – useful with sorted containers • generate_n() – fills elements by invoking callback n times, see later

  20. Modifying: 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

  21. Sorting • sort() – n log(n) sort of the range • merge() – linear merge of sorted 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()

  22. Set operate 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.

  23. Enhanced Iterator Functions further enhance the power of algorithms • iterator movement functions – makes iterator operate as random access regardless of type • reverse iterators – iterate in reverse direction • inserters – target range does not have to match source range

  24. Iterator Movement Functions poor man’s iterator arithmetic implemented as templates • advance(iterator, position) – move iterator,position elements, returns void, iterator needs to be at least input • if iterator is input – moves copy of iterator by repeatedly calling increment • if iterator is random access – calls operator+(position) • next(iterator, position) – returns iterator pointing position elements forward, original iterator is not modified • if iterator is input – repeatedly calls increment • if random access – adds position to iterator • prev(iterator,position) – same as next in reverse direction • distance(firstIterator, lastIterator) – returns the number of elements between firstIterator and lastIterator. If iterators are random access, uses subtract, otherwise repeatedly calls increment

  25. Iterator Adapters: Reverse • declared in <iterator> • reverse_iterator – iterates in reverse order (increment advances backward) • rbegin() – returns reverse iterator starting at the last element of container • rend() – returns iterator before the first element • base() – returns underlying iterator plus one – useful to determine distance to beginning • crbegin() and crend() also exist

  26. Iterator Adapters: Insert • insert iterators – special type of output iterators designed for algorithms (such as copy_if) to insert rather than overwrite elements  do not have to know target range • insert_iterator() • assignment calls insert(position, element)on container, advances insert iterator to the next position • initialized with container, position • inserter(container, position) returns insert_iteratoron this position • useful for associative containers whose keys are usually not modifiable on iteration • back_insert_iterator() – calls push_back() on container • back_inserter(container) returns back_insert_iteratorfor this container • front_insert_iterator() – calls push_front() • elements are inserted sequentially, may be inefficient • increment/decrement have no effect

  27. Algorithms Review • what is half-open range? • what is a callback? function pointer? • lambda function? what is capture? capture block? capture by reference? capture by copy? • functor? advantages/differences with function pointer? • predefined functors? arithmetic? logical? • binder (function adapter)? binder in a callback? • std::function purpose/usage? • algorithm categories • utility • non-modifying: search, comparison, operational, numerical processing • modifying • sorting • set • iterator movement functions? • iterator adapters: inserters/reverse?

More Related