C++进阶篇二:C++标准模版库之算法

news/2024/7/16 8:01:12 标签: c/c++, 数据结构与算法, 人工智能

为什么80%的码农都做不了架构师?>>>   hot3.png

写在<algorithm>头文件之前

在C++STL的头文件<algorithm>中,各式算法函数往往会对支持该算法的最低迭代级别作出要求。任何算法作用的容器或迭代,只有支持的权限等于或高于算法要求的最低迭代级别,才能适用该算法。(关于迭代级别,可参考楼主文章:《一篇文章看懂C++ 标准模板库容器和迭代》,URL:https://my.oschina.net/SamYjy/blog/855953 )比如某个算法需要至少向前迭代级别支持,则该算法可以应用于所有迭代级别高于或等于向前迭代的容器。因此,STL算法函数的学习中,就可以按照算法所支持的迭代级别对算法进行分类。

此外,当对容器作出修改时(比如对vector应用clear或erase方法),在应用方法前的迭代可能会失效。插入(insert操作)对于各容器的作用如下:

  • vector:若vector的空间被重新分配,所有之前的迭代均无效。其他情况下,从插入点到end位置的迭代无效。
  • deque:全部迭代失效。
  • list, forward_list以及顺序关联型容器:全部迭代有效。
  • 非顺序关联型容器:若容器空间被重新分配则所有迭代失效。

当从容器中擦除元素时(erase操作),被擦除部分的迭代失效。另需注意,

  1. 对vector来说,从被擦除位置到end位置的元素全部无效。
  2. 对deque来说,如果队列中间部分元素被擦除,则所有迭代无效。

C++ STL算法查看方式(以transform函数为例):

cppreference 为C++ DOC的一个使用说明网页。网址:http://en.cppreference.com/w/ 在其中可以查到各种算法函数(点击Algorithms library)。例如,查询transform函数可获得以下两条C++11有关信息:

template< class InputIt, class OutputIt, class UnaryOperation >
OutputIt transform( InputIt first1, InputIt last1, OutputIt d_first,
                    UnaryOperation unary_op );

template< class InputIt1, class InputIt2, class OutputIt, class BinaryOperation >
OutputIt transform( InputIt1 first1, InputIt1 last1, InputIt2 first2, 
                    OutputIt d_first, BinaryOperation binary_op );

此处,InputIt就表示输入迭代,OutputIt就表示输出迭代,UnaryOperation表示传入参数为一个的单元操作函数,BinaryOperation表示传入参数为二元的函数。此外,还有ForwardIt表示向前迭代,RandomIt 表示随机存取以及 Compare表示传入函数对象等。

以transform函数为例,第一个重载函数即表示了传入参数前两个为输入迭代,第三个参数为输出迭代以及最后一个参数为单元操作函数指针;而第二个重载函数的不同之处在于最后一个传入参数可以是二元操作函数。

C++ STL常用算法一览:

C++标准模版库中的常用算法非常之多,有90多种。限于篇幅,本文仅仅列举一些《C++11程序设计》中介绍的常用算法,并且将他们按照对应传入参数迭代级别(事实上即为可应用范围从广到窄)的方式进行分类,在文末附上一些算法的使用示例,以便于快速查询算法及其用法。

最低权限为输入输出迭代的函数

  • all_of(iter.cbegin(), iter.cend(), bool_func):判断是否迭代范围内的所有元素都能使bool_func函数为true。返回值为bool。
  • any_of(iter.cbegin(), iter.cend(), bool_func):判断是否迭代范围内的存在元素,能使bool_func函数为true。返回值为bool。
  • accumulate(iter.cbegin(), iter.cend(), initVal, [how_to_accu]):头文件<numeric>,第三个参数为积分的初始值。第四个参数为可选参数,为一个指定了计算积分的方式的函数头。该指定积分方式的函数必须以当前和和下一项为传入值,返回值为当前和与下一项值进行运算之后的结果。
  • copy(iter_begin(), iter_end(), ostream):将迭代范围内的容器拷贝到输出中,本函数要求前两个传入参数至少为输入迭代。它有一个类似方法copy_backward(iter.cbegin(), iter.cend(), output.end()),常用于将元素倒序放入。其它的拷贝函数还有copy_if和copy_n。但是copy_backward前两个参数要求的最低迭代权限为双向迭代。
  • count(iter.cbegin(), iter.cend(), ele):统计ele元素迭代范围内出现的次数。
  • count_if(iter.cbegin(), iter.cend(), bool_func):在迭代范围内统计使得bool_func为true的元素个数.
  • equal(iter1.cbegin(), iter1.cend(), iter2.cbegin(), [predicate]):比较两个数据结构是否内容完全相同,返回值为bool。
  • find(iter.cbegin(), iter.cend(), ele):在迭代范围内寻找ele元素,并返回其迭代位置。若未找到,返回迭代终止位置。本函数前两个参数支持的最低权限为输入迭代。
  • find_if(iter.cbegin(), iter.cend(), bool_func):在迭代范围内寻找第一个使得bool_func为true的元素,并返回其迭代位置。若未找到,返回迭代终止位置。
  • find_if_not(iter.cbegin(), iter.cend(), bool_func):判断是否迭代范围内存在元素,能使bool_func函数为false,返回值为bool。
  • for_each(iter.cbegin(), iter.cend(), func):对迭代范围内的每一个元素按照func函数进行操作。
  • includes(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), [predicate]):检测第二个集合是否包含在第一个集合中,返回值为bool。
  • lexicographical_compare(begin(c1), end(c1), begin(c2), end(c2)):比较内置char数组,返回值为bool。
  • minmax_element(iter.cbegin(), iter.cend(), [predicate]):找到数据结构中的最小最大元素对应的迭代,以对值形式返回。其对应的两个只返回最小最大元素迭代的函数分别为:min_element(iter.cbegin(), iter.cend(), [predicate])和max_element(iter.cbegin(), iter.cend(), [predicate])。
  • mismatch(iter1.cbegin(), iter1.cend(), iter2.cbegin(), [predicate]):比较两个容器中的不同部分,返回值为一个对值。
  • merge(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), output.begin(), [predicate]):将两个已经排序完毕的数据结构归并到result数据结构中。
  • none_of(iter.begin(), iter.end(), bool_func):判断是否迭代范围内的所有元素都能使bool_func函数为false,返回值为bool。
  • remove_copy(iter1.cbegin(), iter1.cend(), output.cbegin(), ele):将数据结构1中迭代范围内的元素复制到输出迭代中,并移除所有ele元素。返回值为被复制到输出迭代的最后一个元素所对应的迭代。
  • remove_copy_if(iter1.cbegin(), iter1.cend(), output.begin(), bool_func):可参照remove和remove_copy之间的关系从remove_if函数推知该函数功能,返回值为最后一个被复制元素的迭代。
  • replace_copy(iter1.cbegin(), iter1.cend(), output.begin(), ele1, ele2):复制数据结构迭代范围内的数据,粘帖到数据结构2迭代起始位置并将结构1中的ele1元素全部用ele2元素替代,返回值同考remove_copy。
  • replace_copy_if(iter1.cbegin(), iter1.cend(), iter2.start(), bool_func, ele):功能可参照remove_copy_if得知,返回值和权限同remove_copy_if函数。
  • set_difference(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), difference.begin(), [predicate]):作U1 - U2的集合操作。
  • set_intersection(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), difference.begin(), [predicate]):作U1交U2的集合操作。
  • set_symmetric_difference(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), difference.begin(), [predicate]):选出集合1和2分别独有的元素,存入difference数据结构中。
  • set_union(iter1.cbegin(), iter1.cend(), iter2.cbegin(), iter2.cend(), difference.begin(), [predicate]):作U1并U2的集合操作。
  • transform(iter1.cbegin(), iter1.cend(), [iter2.begin()], output.begin(), opfunc):将迭代范围内的每一个元素(数据结构2存在时为每一对元素)按照opfunc指定的方法处理,输出到output数据结构中。若可选参数被传入时,opfunc必须为一个二元操作函数,否则为一元操作函数。
  • unique_copy(iter.begin(), iter.end(), output, [predicate]):将迭代范围内的元素去重吼存入output数据结构中。

注:

  1. 未特殊说明时,iter指输入迭代,output指输出迭代。
  2. 此处集合操作未特殊声明,应理解为对数据结构的操作,而非数学定义的集合,因为操作中允许重复元素。

最低权限为向前迭代的函数

  • binary_search(iter.cbegin(), iter.cend(), ele, [predicate]):通过二分查找的方式在迭代范围内(要求已排序)判断迭代范围内是否存在该元素,返回值为bool。
  • eqaul_range(iter.cbegin(), iter.cend(), ele, [predicate]):查找最早和最晚适合插入ele元素的插入点位置对应的迭代,返回值为表示这两个位置的对值,类型均为向前迭代。
  • fill(iter.begin(), iter.end(), data):用数据data将指定数据结构迭代范围内的位置填满。若未填满这个数据结构,其余部分保持原值。
  • fill_n(iter.begin(), n, data):从起始迭代位置将data向数据结构中填入n次。若填充过程中遇到数据结构结束,则填充到结束位置为止。
  • generate(iter.begin(), iter.end(), data):用数据data将指定数据结构迭代范围填满。若未填满这个数据结构,其余部分保持原值。
  • generate_n(iter.begin(), iter.end(), data):从起始迭代位置将data向数据结构中填入n次。若填充过程中遇到数据结构结束,则填充到结束位置为止。
  • iter_swap(iter.begin(), iter.end()):通过使用迭代器的方式交换这两个迭代分别对应的元素。
  • lower_bound(iter.cbegin(), iter.cend(), ele, [predicate]):查找最早适合插入ele元素的插入点位置对应的迭代,返回值为表示该位置的向前迭代。
  • min_element(iter.begin(), iter.end(), [predicate]):在迭代范围内找出最小元素首次出现所在的迭代位置,返回值为该位置的向前迭代。
  • max_element(iter.begin(), iter.end(), [predicate]):在迭代范围内找出最大元素首次出现所在的迭代位置,返回值同上。
  • minmax_element(iter.begin(), iter.end(), [predicate]):在迭代范围内分别找出最小最大元素首次出现所在的迭代位置,返回值为对值,第一个值表示最小元素,第二个则为最大元素。
  • remove(iter.begin(), iter.end(), ele):移去数据结构中迭代范围内出现的所有ele元素,返回值为最后一个未被移除的元素的迭代位置。
  • remove_if(iter.begin(), iter.end(), boo_func):在迭代范围内移去所有符合满足使得用户定义的bool函数为true的元素,返回值为最后一个未被移除的元素的迭代位置。
  • replace(iter.begin(), iter.end(), ele1, ele2):将数据结构迭代范围内的所有ele1元素替换为ele2元素。
  • replace_if(iter.begin(), iter.end(), bool_func, ele):在迭代范围内将符合满足用户定义的bool函数为true的元素全部替换为元素ele。
  • swap_ranges(iter.begin(), iter.end(), iter.start()):将迭代范围内的元素与从iter_start()位置开始的元素进行交换。两个范围不能重叠,但可以是同一个数据结构内的范围,也可是不同数据结构的范围。
  • unique(iter_begin(), iter_end()):返回迭代范围内指向数据结构最末单个元素的迭代。
  • upper_bound(iter.cbegin(), iter.cend(), ele, [predicate]):查找最晚适合插入ele元素的插入点位置对应的迭代,返回值为表示该位置的向前迭代。

最低权限为双向迭代的函数

  • inplace_merge(iter.begin(), iter.checkpoint(), iter.end()):将数据结构内部迭代范围内的元素进行归并。其中,要求begin至checkpoint(不包括)以及从checkpoint(包括)至终止位置的元素都分别相应已经排序。
  • reverse(iter.begin(), iter.end()):倒置迭代范围内的所有元素。
  • reverse_copy(iter.begin(), iter.end(), output):将数据结构中的元素倒置后置入输出容器中。

最低权限为随机存取的函数

  • make_heap(iter.begin(), iter.end(), [predicate]):用数据结构迭代范围内的元素建堆。
  • push_heap(iter.begin(), iter.end(), [predicate]):将数据结构end位置元素加入由其它元素构成的堆中。(假设其他元素已构成堆)
  • pop_heap(iter.begin(), iter.end(), [predicate]):将堆顶元素推出堆,放在end位置,并将剩余元素进行调堆。
  • random_shuffle(iter.begin(), iter.end(), [rand_generator]):打乱迭代范围内元素,其中rand_generator为可选函数。
  • sort(iter.begin(), iter.end(), [predicate]):将迭代范围内的数据元素进行排序。
  • sort_heap(iter.begin(), iter.end(), [predicate]):根据已有堆进行堆排序。

STL函数若干注意:

  1. fill 和generate是有区别的,简而言之,fill只是从头到尾填充同一个浅拷贝的元素,而generate则是生成深拷贝的元素(从样例程序和参考资料 中都可以看出来)
  2. 参数中若有c开头的迭代(cbegin或cend)表示此处可以使用常量迭代(作用类似于常量指针),没有则必须使用变量迭代。
  3. 迭代范围值从迭代起始位置到迭代终止位置。
  4. 未经特殊说明,本文所指的迭代起始位置包括起始的那个元素的迭代,而迭代终止位置则不包括。
  5. 凡是返回元素所在位置迭代的,若未查找到该元素或数据结构中所有元素都已遍历,则返回end位置的迭代,没有实际意义。
  6. 对值(pair object)是指由两个分别指向迭代起始和迭代终止位置组成的一对指针,一般形式为``` auto p = pair_obj;
1. 文中由中括号包括的为可选参数,[predicate]是C++函数对象,可以是函数指针、函数对象和lambda表达式,关于此参数的使用,可以详见楼主博客《小论C++函数对象在STL算法函数中的应用》,URL:https://my.oschina.net/SamYjy/blog/878125。

### 仅针对排序后的数据结构进行操作的算法:
binary_search, lower_bound, upper_bound, equal_range, includes, set_difference, set_intersection, set_symmetric_difference, set_union。(可以简要概括为二分查找、范围算法和集合操作)

例1:fill和generate函数使用示例

#include <iostream> #include <algorithm> // algorithm definitions #include <array> // array class-template definition #include <iterator> // ostream_iterator using namespace std;

char nextLetter(); // prototype of generator function

int main() { array< char, 10 > chars; ostream_iterator< char > output(cout, " "); fill(chars.begin() + 1, chars.end(), nextLetter()); // fill chars with 5s

cout << "chars after filling with 5s:\n";
copy(chars.cbegin(), chars.cend(), output);

// fill first five elements of chars with As
fill_n(chars.begin() + 8, 5, 'X');

cout << "\nchars after filling five elements with As:\n";
copy(chars.cbegin(), chars.cend(), output);

// generate values for all elements of chars with nextLetter
generate(chars.begin(), chars.end(), nextLetter);

cout << "\nchars after generating letters A-J:\n";
copy(chars.cbegin(), chars.cend(), output);

// generate values for first five elements of chars with nextLetter
generate_n(chars.begin(), 5, nextLetter);

cout << "\nchars after generating K-O for the"
	<< " first five elements:\n";
copy(chars.cbegin(), chars.cend(), output);
cout << endl;

} // end main

// generator function returns next letter (starts with A) char nextLetter() { static char letter = 'A'; return letter++; } // end function nextLetter

![输入图片说明](https://static.oschina.net/uploads/img/201703/19152113_EaEm.png "在这里输入图片标题")

备注:因为fill只是填入对于同一个元素复制第一次的拷贝,所以会发现全部插入的是暂存字符串A。而因为generate使用的是深拷贝,所以输出的字符串从B开始了。
此外,由于generate函数在C++标准文档中的定义是:

template<class ForwardIterator, class Generator>

其中Generator事实上可以为函数指针、函数对象或者lambda表达式。

例2:比较函数equal, mismatch以及lexicographical_compare示例:

#include <iostream> #include <algorithm> // algorithm definitions #include <array> // array class-template definition #include <iterator> // ostream_iterator

using namespace std;

int main() { const size_t SIZE = 10; array< int, SIZE > a1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; array< int, SIZE > a2( a1 ); // initializes a2 with copy of a1 array< int, SIZE > a3 = { 1, 2, 3, 4, 1000, 6, 7, 8, 9, 10 }; ostream_iterator< int > output( cout, " " );

// compare a1 and a2 for equality bool result = equal( a1.cbegin(), a1.cend(), a2.cbegin() ); cout << "a1 " << ( result ? "is" : "is not" ) << " equal to a2." << endl;

// compare a1 and a3 for equality result = equal( a1.cbegin(), a1.cend(), a3.cbegin() ); cout << "a1 " << ( result ? "is" : "is not" ) << " equal to a3. " << endl;

// check for mismatch between a1 and a3
auto location = mismatch( a1.cbegin(), a1.cend(), a3.cbegin() ); cout << "\nThere is a mismatch between a1 and a3 at location " << ( location.first - a1.begin() ) << "\nwhere a1 contains " << *location.first << " and a3 contains " << *location.second
<< "\n" << endl;

char c1[ SIZE ] = "HELLO"; char c2[ SIZE ] = "BYE BYE";

// perform lexicographical comparison of c1 and c2 result = lexicographical_compare( begin( c1 ), end( c1 ), begin( c2 ), end( c2 ) ); cout << c1 << ( result ? " is less than " : " is greater than or equal to " ) << c2 << endl; } // end main

![输入图片说明](https://static.oschina.net/uploads/img/201704/13210309_1Iy5.png "在这里输入图片标题")


例3:移除类算法remove, remove_if, remove_copy以及remove_copy_if示例:

#include <iostream> #include <algorithm> // algorithm definitions #include <array> // array class-template definition #include <iterator> // ostream_iterator using namespace std;

bool greater9( int ); // prototype

int main() { const size_t SIZE = 10; array< int, SIZE > init = { 10, 2, 10, 4, 16, 6, 14, 8, 12, 10 }; ostream_iterator< int > output( cout, " " );

array< int, SIZE > a1( init ); // initialize with copy of init cout << "a1 before removing all 10s: "; copy( a1.cbegin(), a1.cend(), output ); cout << endl;

// remove all 10s from a1 auto newLastElement = remove( a1.begin(), a1.end(), 10 ); cout << "a1 after removing all 10s: "; copy( a1.begin(), newLastElement, output ); cout << endl;

array< int, SIZE > a2( init ); // initialize with copy of init array< int, SIZE > c = { 0 }; // initialize to 0s

// copy from a2 to c, removing 10s in the process remove_copy( a2.cbegin(), a2.cend(), c.begin(), 10 ); cout << "\nc after removing all 10s from a2: "; copy( c.cbegin(), c.cend(), output ); cout << endl;

array< int, SIZE > a3( init ); // initialize with copy of init

// remove elements greater than 9 from a3 newLastElement = remove_if( a3.begin(), a3.end(), greater9 ); cout << "a3 after removing all elements greater than 9: "; copy( a3.begin(), newLastElement, output ); cout << endl;

array< int, SIZE > a4( init ); // initialize with copy of init array< int, SIZE > c2 = { 0 }; // initialize to 0s

// copy elements from a4 to c2, removing elements greater // than 9 in the process, greater9 is only function header. remove_copy_if( a4.begin(), a4.end(), c2.begin(), greater9 ); cout << "c2 after removing all elements" << "greater than 9 from a4: "; copy( c2.cbegin(), c2.cend(), output ); cout << endl; } // end main

// determine whether argument is greater than 9 bool greater9( int x ) { return x > 9; } // end function greater9


![输入图片说明](https://static.oschina.net/uploads/img/201704/13210826_qKo3.png "在这里输入图片标题")

例4:常用数值操作random_shuffle, count, count_if, min_element, max_element, minmax_element, accumulate, for_each以及transform操作示例:

// Fig. 16.5: fig16_05.cpp // Mathematical algorithms of the Standard Library. #include <iostream> #include <algorithm> // algorithm definitions
#include <numeric> // accumulate is defined here #include <array> #include <iterator> #include <random> #include <ctime>

using namespace std;

bool greater9( int ); // predicate function prototype void outputSquare( int ); // output square of a value int sumMultiply( int, int ); // calculate cube of a value int myrandom(int i) {
srand(time(0)); return std::rand() % i; } bool reverseCompare(int num1, int num2){ return num1 > num2; } int howToAccumulate(int sum, int item){ return sum + (item << 1); } int calculateCube(int val){ return val * val * val;}

int main() { const int SIZE = 10; array< int, SIZE > a1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; ostream_iterator< int > output( cout, " " );

cout << "a1 before random_shuffle: "; copy( a1.cbegin(), a1.cend(), output );

random_shuffle(a1.begin(), a1.end(), myrandom);

cout << "\na1 after random_shuffle: "; copy( a1.cbegin(), a1.cend(), output );

array< int, SIZE > a2 = { 100, 2, 8, 1, 50, 3, 8, 8, 9, 10 }; cout << "\n\na2 contains: "; copy( a2.cbegin(), a2.cend(), output );

// count number of elements in a2 with value 8 int result = count( a2.cbegin(), a2.cend(), 8 ); cout << "\nNumber of elements matching 8: " << result;

// count number of elements in a2 that are greater than 9 result = count_if( a2.cbegin(), a2.cend(), greater9 ); cout << "\nNumber of elements greater than 9: " << result;

// locate minimum element in a2 cout << "\n\nMinimum element in a2 is: " << *( min_element( a2.cbegin(), a2.cend(), reverseCompare ) );

// locate maximum element in a2 cout << "\nMaximum element in a2 is: " << *( max_element( a2.cbegin(), a2.cend() ) );

// locate minimum and maximum elements in a2 auto minAndMax = minmax_element( a2.cbegin(), a2.cend() ); cout << "\nThe minimum and maximum elements in a2 are " << *minAndMax.first << " and " << *minAndMax.second << ", respectively";

// calculate sum of elements in a1 cout << "\n\nThe twice of the total of the elements in a1 is: " << accumulate( a1.cbegin(), a1.cend(), 0, howToAccumulate );

// output square of every element in a1 cout << "\n\nThe square of every integer in a1 is:\n"; for_each( a1.cbegin(), a1.cend(), outputSquare );

array< int, SIZE > multiplieSum; // instantiate multiplieSum array<int, SIZE> cubes;

// calculate cube of each element in a1; place results in cubes transform( a1.cbegin(), a1.cend(), a2.cbegin(), multiplieSum.begin(), sumMultiply ); cout << "\n\nThe sum of muliply of one element in a1 and another in a2 is:\n"; copy( multiplieSum.cbegin(), multiplieSum.cend(), output ); cout << endl;

transform( a1.cbegin(), a1.cend(), cubes.begin(), calculateCube ); cout << "\n\nThe cubes of all elements in a1 is:\n"; copy( cubes.cbegin(), cubes.cend(), output ); cout << endl; } // end main

// determine whether argument is greater than 9 bool greater9( int value ) { return value > 9; } // end function greater9

// output square of argument void outputSquare( int value ) { cout << value * value << ' '; } // end function outputSquare

// return cube of argument int sumMultiply( int val1, int val2 ) { return val1 * val2; } // end function calculateCube

![输入图片说明](https://static.oschina.net/uploads/img/201704/01155242_YL02.png "在这里输入图片标题")

例5:常用查找、排序操作find, find_if, sort, binary_search, all_of, any_of, none_of和find_if_not操作使用示例:

#include <iostream> #include <algorithm> // algorithm definitions #include <array> // array class-template definition #include <iterator> using namespace std;

bool greater10( int value ); // predicate function prototype bool intCompare(int num1, int num2){ return num1 > num2; }

int main() { const size_t SIZE = 10; array< int, SIZE > a = { 10, 2, 17, 5, 16, 8, 13, 11, 20, 7 }; ostream_iterator< int > output( cout, " " );

cout << "array a contains: "; copy( a.cbegin(), a.cend(), output ); // display output vector

// locate first occurrence of 16 in a auto location = find( a.cbegin(), a.cend(), 16 );

if ( location != a.cend() ) // found 16 cout << "\n\nFound 16 at location " << ( location - a.cbegin() ); else // 16 not found cout << "\n\n16 not found";

// locate first occurrence of 100 in a location = find( a.cbegin(), a.cend(), 100 );

if ( location != a.cend() ) // found 100 cout << "\nFound 100 at location " << ( location - a.cbegin() ); else // 100 not found cout << "\n100 not found";

// locate first occurrence of value greater than 10 in a location = find_if( a.cbegin(), a.cend(), greater10 );

if ( location != a.cend() ) // found value greater than 10 cout << "\n\nThe first value greater than 10 is " << *location << "\nfound at location " << ( location - a.cbegin() ); else // value greater than 10 not found cout << "\n\nNo values greater than 10 were found";

// sort elements of a //sort( a.begin(), a.end() ); //Sort in reverse order: sort( a.begin(), a.end(), intCompare ); cout << "\n\narray a after sort: "; copy( a.cbegin(), a.cend(), output );

// use binary_search to locate 13 in a if ( binary_search( a.cbegin(), a.cend(), 13, intCompare ) ) cout << "\n\n13 was found in a, location: " << (find( a.cbegin(), a.cend(), 13 ) - a.cbegin()) << endl; else cout << "\n\n13 was not found in a";

// use binary_search to locate 100 in a if ( binary_search( a.cbegin(), a.cend(), 100 ) ) cout << "\n100 was found in a"; else cout << "\n100 was not found in a";

// determine whether all of the elements of a are greater than 10 if ( all_of( a.cbegin(), a.cend(), greater10 ) ) cout << "\n\nAll the elements in a are greater than 10"; else cout << "\n\nSome elements in a are not greater than 10";

// determine whether any of the elements of a are greater than 10 if ( any_of( a.cbegin(), a.cend(), greater10 ) ) cout << "\n\nSome of the elements in a are greater than 10"; else cout << "\n\nNone of the elements in a are greater than 10";

// determine whether none of the elements of a are greater than 10 if ( none_of( a.cbegin(), a.cend(), greater10 ) ) cout << "\n\nNone of the elements in a are greater than 10"; else cout << "\n\nSome of the elements in a are greater than 10";

// locate first occurrence of value that's not greater than 10 in a location = find_if_not( a.cbegin(), a.cend(), greater10 );

if ( location != a.cend() ) // found a value less than or eqaul to 10 cout << "\n\nThe first value not greater than 10 is " << *location << "\nfound at location " << ( location - a.cbegin() ); else // no values less than or equal to 10 were found cout << "\n\nOnly values greater than 10 were found";

cout << endl; } // end main

// determine whether argument is greater than 10 bool greater10( int value ) { return value > 10; } // end function greater10


![输入图片说明](https://static.oschina.net/uploads/img/201704/02211214_A81c.png "在这里输入图片标题")

例6:swap_ranges, sort, merge, unique函数使用示例:

// Fig. 16.7: fig16_07.cpp // Algorithms iter_swap, swap and swap_ranges. #include <iostream> #include <array> #include <algorithm> #include <iterator> using namespace std;

// sort using a custom function object

struct { bool operator()(int a, int b) { return a > b; } } customLess;

int main() { const size_t SIZE = 10; array< int, SIZE > a = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; array< int, SIZE > b = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; array<int, 5> c = {15, 13, 11, 9, 7}; ostream_iterator< int > output( cout, " " );

// swap elements in first five elements of array a with // elements in last five elements of array a swap_ranges( a.begin(), a.begin() + 5, b.begin() + 5 );

cout << "\nArray a, b after the process: " << endl; copy( a.cbegin(), a.cend(), output ); cout << endl; copy( b.cbegin(), b.cend(), output ); cout << endl;

sort(b.begin(), b.end(), std::greater<int>()); copy( b.cbegin(), b.cend(), output ); cout << endl; vector<int> result; merge(b.cbegin(), b.cend(), c.cbegin(), c.cend(), back_inserter(result), std::greater<int>()); /Below is also available, but is in C-Style: merge(b.cbegin(), b.cend(), c.cbegin(), c.cend(), back_inserter(result), customLess);/

cout << "Merge result: "; copy( result.cbegin(), result.cend(), output ); cout << endl;

auto endLocation = unique(result.begin(), result.end()); for(auto p = endLocation; p <= result.end(); p++) result.pop_back();

cout << "After unique and reverse, result contains: "; reverse(result.begin(), result.end()); copy(result.begin(), result.end(), output); cout << endl; } // end main

![输入图片说明](https://static.oschina.net/uploads/img/201704/11221910_saw0.png "在这里输入图片标题")

例7:集合操作includes, set_difference, set_intersection, set_symmetric_difference和set_union操作示例:

#include <iostream> #include <array> #include <algorithm> // algorithm definitions #include <iterator> // ostream_iterator using namespace std;

int main() { const size_t SIZE1 = 10, SIZE2 = 5, SIZE3 = 20; array< int, SIZE1 > a1 = { 1, 2, 2, 4, 5, 6, 7, 8, 9, 10 }; array< int, SIZE2 > a2 = { 4, 5, 6, 7, 8 }; array< int, SIZE2 > a3 = { 4, 5, 6, 11, 15 }; ostream_iterator< int > output( cout, " " );

// determine whether a2 is completely contained in a1 if ( includes( a1.cbegin(), a1.cend(), a2.cbegin(), a2.cend() ) ) cout << "a1 includes a2"; else cout << "a1 does not include a2";

cout << endl;

// determine whether a3 is completely contained in a1 if ( includes( a1.cbegin(), a1.cend(), a3.cbegin(), a3.cend() ) ) cout << "a1 includes a3"; else cout << "a1 does not include a3"; cout << "\n" << endl;

array< int, SIZE1 > difference;

// determine elements of a1 not in a2 auto result1 = set_difference( a1.cbegin(), a1.cend(), a2.cbegin(), a2.cend(), difference.begin() ); cout << "set_difference of a1 and a2 is: "; copy( difference.begin(), result1, output ); cout << endl;

array< int, SIZE1 > intersection;

// determine elements in both a1 and a2 auto result2 = set_intersection( a1.cbegin(), a1.cend(), a2.cbegin(), a2.cend(), intersection.begin() ); cout << "set_intersection of a1 and a2 is: "; copy( intersection.begin(), result2, output ); cout << endl;

array< int, SIZE1 + SIZE2 > symmetric_difference;

// determine elements of a1 that are not in a2 and // elements of a2 that are not in a1 auto result3 = set_symmetric_difference( a1.cbegin(), a1.cend(), a3.cbegin(), a3.cend(), symmetric_difference.begin() );
cout << "set_symmetric_difference of a1 and a3 is: "; copy( symmetric_difference.begin(), result3, output ); cout << endl;

array< int, SIZE3 > unionSet;

// determine elements that are in either or both sets auto result4 = set_union( a1.cbegin(), a1.cend(), a3.cbegin(), a3.cend(), unionSet.begin() ); cout << "set_union of a1 and a3 is: "; copy( unionSet.begin(), result4, output ); cout << endl; } // end main


![输入图片说明](https://static.oschina.net/uploads/img/201704/13205202_Csvi.png "在这里输入图片标题")

例8:堆有关操作make_heap, sort_heap, push_heap以及pop_heap:

#include <iostream> #include <algorithm> #include <array> #include <vector> #include <iterator> using namespace std;

int main() { const size_t SIZE = 10; array< int, SIZE > init = { 3, 100, 52, 77, 22, 31, 1, 98, 13, 40 }; array< int, SIZE > a( init ); // copy of init
ostream_iterator< int > output( cout, " " );

make_heap( a.begin(), a.end() ); // create heap from array a cout << "Array a after make_heap: "; copy( a.cbegin(), a.cend(), output ); cout << endl;

sort_heap( a.begin(), a.end() ); // sort elements with sort_heap cout << "Array a after sort_heap: "; copy( a.cbegin(), a.cend(), output ); cout << endl;

// perform the heapsort with push_heap and pop_heap cout << "\nArray init contains: "; copy( init.cbegin(), init.cend(), output ); // display array init cout << endl;

vector< int > v;

// place elements of array init into v and // maintain elements of v in heap for ( size_t i = 0; i < init.size(); ++i ) { v.push_back( init[ i ] ); push_heap( v.begin(), v.end() );
cout << "\nv after push_heap(init[" << i << "]): "; copy( v.cbegin(), v.cend(), output ); } // end for

cout << endl;

// remove elements from heap in sorted order for ( size_t j = 0; j < v.size(); ++j ) { cout << "\nv after " << v[ 0 ] << " popped from heap\n"; pop_heap( v.begin(), v.end() - j ); copy( v.cbegin(), v.cend(), output ); } // end for

cout << endl; } // end main


![输入图片说明](https://static.oschina.net/uploads/img/201704/13205844_FYHN.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201704/13205856_qubG.png "在这里输入图片标题")

备注:限于篇幅,本文不详细介绍C++11的is_heap和is_heap_until函数。


参考资料:

1. C++编程官方参考资料cpp reference:URL: http://en.cppreference.com/w/cpp/algorithm
1. 华秋实专栏,fill和generate的区别,URL:http://blog.csdn.net/yockie/article/details/8941649
1. Paul Deitel & Harvey Deitel, C++11程序设计(英文版)(第2版)
1. SamYjy的OSC博客,《一篇文章看懂C++ 标准模板库容器和迭代》

转载于:https://my.oschina.net/Samyan/blog/879210


http://www.niftyadmin.cn/n/1665940.html

相关文章

cookie 与 SSO 的两三事

前言 前面的文章记录了proxy代理后端接口&#xff0c;其实践过程中也不乏踩坑之处。 SSO单点登录 这里有一篇文章写得不错&#xff0c;分析了淘宝、天猫的登录场景(漫谈单点登录)。 COOKIE 关于cookie的知识自己搜&#xff0c;我这就不废话了。关键看请求的response headers &a…

Katalon Studio 自动化测试工具介绍

前言 在软件测试这条道路上&#xff0c;大部分的职业技能发展道路都会是功能测试-> 自动化测试-> 性能测试-> 安全测试/测试开发。 但是却有着一部分人起初进入软件测试这一行看重的就是软件测试属于 IT 行业&#xff0c;门槛比较低&#xff0c;不需要代码基础。这就…

优秀的产品经理,必须翻越这三座大山

作为一个资深产品经理&#xff0c;这几年工作中遇到的挫折和收获&#xff0c;数也数不清。看到用户数的不断增长和好评我会犹如打了鸡血&#xff0c;听到伙伴的质疑和用户的指责我也会在回家地铁上默默掉眼泪&#xff0c;后悔当初的选择。对于新入行的童鞋&#xff0c;我这个老…

《深入理解计算机系统》使用指南

转自&#xff1a;https://book.douban.com/review/5627139/#comments Chapter 1 A Tour of Computer System 一个对计算机系统总体的介绍&#xff0c;简单明了。 应试 ★★★&#xff1a;可能在笔试中会有一些整体上的概念题。 修炼 ★: 属于计算机最基本的概念。 chapter 2 …

Node核心模块Http应用-防盗链

防盗链的原理是通过判断请求源地址的req的headers里面的host和referer进行判断&#xff0c;如果两个相等证明是同一个源下返回正确图片&#xff0c;不相同返回错误图片。 let fs require(fs);let path require(path);let url require(url);let http require(http);let whit…

web 自动化测试,一定得掌握的 8 个核心知识点

使用 cypress 进行端对端测试&#xff0c;和其他的一些框架有一个显著不同的地方&#xff0c;它使用 JavaScript 作为编程语言。传统主流的 selenium 框架是支持多语言的&#xff0c;大多数 QA 会的 python 和 Java 语言都可以编写 selenium 代码&#xff0c;遇到需要编写 js 代…

memset函数使用方法

将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值&#xff0c; 块的大小由第三个参数指定&#xff0c;这个函数通常为新申请的内存做初始化工作&#xff0c; 其返回值为指向S的指针。 需要的头文件在C中 <string.h>在C中 <cstring>更详细的解说…

JavaScript 九种跨域方式实现原理

前言 前后端数据交互经常会碰到请求跨域&#xff0c;什么是跨域&#xff0c;以及有哪几种跨域方式&#xff0c;这是本文要探讨的内容。 一、什么是跨域&#xff1f; 1.什么是同源策略及其限制内容&#xff1f; 同源策略是一种约定&#xff0c;它是浏览器最核心也最基本的安全功…