一、泛型算法泛型算法这个概念是针对容器操作的,我们知道,c++11的顺序容器有vector,list,deque等,对于这些容器,c++11并没给出相应的增删改查方法,而是定义了一组泛型算法
一般的泛型算法都定义在#include <algorithm>中,对于数值的有些算法则定义在#include <numeric>中
1、find
vector<int>::const_iterator result = find(vec.begin(), vec.end(), search_value)
找到就返回指向该元素的迭代器,没找到就返回第二个迭代器实参
vector<string> vec_test = { "I","love","c++" ,"and","I","know","how","to","user","it"}; vector<string>::iterator it = find(vec_test.begin(), vec_test.end(), "it"); //最后一个值可以是lambda表达式,精确筛选 cout<<*it<< endl;
由于 find 运算是基于迭代器的,因此可在任意容器中使用相同的 find 函数查找值。
类似地,由于指针的行为与作用在内置数组上的迭代器一样,因此也可以使用 find 来搜索数组:int ia[6] = {27, 210, 12, 47, 109, 83};
int *result = find(ia, ia + 6, 12);
2、accumulate
该算法在 numeric 头文件中定义。假设 vec 是一个 int 型的 vector 对象,下面的代码:
int sum = accumulate(vec.begin(), vec.end(), 42);
将 sum 设置为 vec 的元素之和再加上 42。第三个形参则是累加的初值。
用于指定累加起始值的第三个实参是必要的,因为 accumulate 对将要累加的元素类型一无所知
这个事实有两层含义。首先,调用该函数时必须传递一个起始值,否则,accumulate 将不知道使用什么起始值。其次,容器内的元素类型必须与第三个实参的类型匹配,或者可转换为第三个实参的类型。
vector<int> vec_test = {15,8,2,3,4,8,6,3,5,1,5,57}; int sum = accumulate(vec_test.cbegin(),vec_test.cend(),0); cout << sum;
3、find_first_of
这个算法带有两对迭代器参数来标记两段元素范围,在第一段范围内查找与第二段范围中任意元素匹配的元素,然后返回一个迭代器,指向第一个匹配的元素。如果找不到元素,则返回第一个范围的 end 迭代器。
vector<string> vec_1{"what", "did", "i", "do"}; vector<string> vec_2{ "no", "did", "you", "do" }; vector<string>::const_iterator it = find_first_of(vec_1.cbegin(), vec_1.cend(), vec_2.cbegin(),vec_2.cend()); cout << *it << endl;
4、fill
vector<int> vec_test = {1,3,5,85,7,8,4,5}; fill(vec_test.begin(), vec_test.end(), 0); vector<int>::iterator it = vec_test.begin(); while (it!= vec_test.end()) { cout << *it << endl; it++; }
5、fill _n
带有的参数包括:一个迭代器、一个计数器以及一个值。该函数从迭代器指向的元素开始,将指定数量的元素设置为给定的值。fill_n 函数假定对指定数量的元素做写操作是安全的。
初学者常犯的错误的是:在没有元素的空容器上调用 fill_n 函数(或者类似的写元素算法)。
it = vec_test.begin(); fill_n(vec_test.begin(), 2,10); while (it != vec_test.end()) { cout << *it << endl; it++; }
6、back_inserter
这个函数是迭代器适配器,插入迭代器可以给基础容器添加元素的迭代器
使用 back_inserter 可以生成一个指向 fill_n 写入目标的迭代器:
vector<int> vec; // empty fill_n(back_inserter(vec), 10, 0); auto it = vec.begin(); while (it != vec.end()) { cout << *it << endl; it++; }
7、copy
list<int> ilst = { 34,5,43,43,543,58,87,9,1,3,5,45,4 }; vector<int> ivec; // empty copy(ilst.begin(), ilst.end(), back_inserter(ivec)); auto it = ivec.begin(); while (it != ivec.end()) { cout << *it << endl; it++; }
8、replace
这个算法接受第三个迭代器实参,指定保存调整后序列的目标位置。
如果不想改变原来序列,调用replace_copy()
调用该函数后,ilst 没有改变,ivec 存储 ilst 一份副本,而 ilst 内所有的 0 在 ivec 中都变成了 42。
list<int> ilst = { 24,24,24,24,24 }; replace(ilst.begin(), ilst.end(), 24, 42); auto it = ilst.begin(); while (it != ilst.end()) { cout << *it << endl; it++; } list<int> ilst = { 24,24,24,24,24 }; vector<int> vec; replace_copy(ilst.begin(), ilst.end(),back_inserter(vec),24, 42); auto it = ilst.begin(); while (it != ilst.end()) { cout << *it << endl; it++; } auto it2 = vec.begin(); while (it2 != vec.end()) { cout << *it2 << endl; it2++; }
9、
对容器元素重新排序的算法
按单词长度排序 sort排序
去掉所有重复单词 调用 unique“删除”了相邻的重复值。给“删除”加上引号是因为 unique 实际上并没有删除任何元素,而是将无重复的元素复制到序列的前端,从而覆盖相邻的重复元素。unique 返回的迭代器指向超出无重复的元素范围末端的下一位置。然后用erase
统计长度等于或超过6个字符的单词个数
auto GT6 = [](const string &s) -> bool { return s.size() >= 5; }; vector<string> vec = { "ok","work","over","handsome","red","red","slow","a","the","turtle" }; sort(vec.begin(), vec.end()); //排序 vector<string>::iterator it = unique(vec.begin(), vec.end()); //移动重复元素,返回不重复的下一个位置的迭代器 vec.erase(it, vec.end()); //删除重复元素 vector<string>::iterator it1 = vec.begin(); int n = 0; while (it1 != vec.end()) { if (GT6(*it1)) n++; cout << *it1++ << " "; } cout << endl << "the words size no less than 5 have :" << n << endl;