泛型算法 lambda表达式

时间:2021-03-21 18:44:47

泛型算法介绍

泛型算法大多数是独立于任何特定的容器的,定义在头文件algorithmnumeric中,算法不直接操作容器,而是遍历由两个迭代器指定的一个元素范围。

泛型算法种类

只读算法

find(vec.cbegin(),vec.cend(),0);//返回迭代器 
count(vec.cbegin(),vec.cend(),0);//返回给定值在序列中出现的次数
int sum = accumulate(vec.cbegin(),vec.cend(),0);//sum设置为vec中元素的和,定义在numeric中
string sum = accumulate(vec.cbegin(),vec.cend(),string("");//string才有加法运算,char * 类型没有
equal(roster1.cbegin(), roster1.cend(),roster2.cbegin());//可以用来比较不同容器内的元素,只要能用==比较就可以,第二个序列至少与第一个一样长!

写容器元素的算法

    fill(vec.begin(), vec.end(), 0);//将每个元素重置为0,注意不能超出原有vec的size,否则会出错
fill_n(vec.begin(), vec.size(), 0);

auto ret = copy(begin(a1), end(a1), a2);//拷贝到新的数组中去,返回的是尾元素之后的位置
replace(list.begin(), list.end(), 0, 42);//把所有0的值取代为42
replace_copy(list.begin(), list.end(), back_inserter(vec), 0,42);//取代后拷贝到新的容器中

size是指出vector存有元素的个数,capacity是指出现有vector可以存放多少元素

插入迭代器

    #include <iterator> 
vector<int> vec;
auto it = back_inserter(vec);//返回一个插入迭代器
*it = 42;
*it = 50;
cout << vec.size() << endl;//结果为2,调用一次相当于一次push_back;
fill_n(back_inserter(vec), 10, 0);
cout << vec.size() << endl;//结果为12!

重排容器

删除序列中重复元素的程序:

#include <iostream> 
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
void elimDups(vector<string> & words) {
sort(words.begin(), words.end());//排序
auto end_unique = unique(words.begin(), words.end());//不重复元素出现在开始部分,返回不重复区域之后一个元素的迭代器
words.erase(end_unique, words.end());//删除掉多余的
}
int main() {
vector<string> vec;
vec.push_back("e");
vec.push_back("b");
vec.push_back("c");
vec.push_back("c");
vec.push_back("d");
vec.push_back("d");
vec.push_back("a");
elimDups(vec);
cout << vec.size() << endl;
return 0;
}

swap操作

操作于容器(除了array,string)迭代器,指针,引用仍指向原来元素值,操作于string会失效,操作于array迭代器,指针,引用指向原来元素位置但值改变啦!
swap(vec1,vec2);

定制操作

自定义函数,然后向算法传递参数取代原有的比较函数(如<运算符)

bool isshorter(const string &  s1, const string & s2) {
return s1.size() < s2.size();
}
sort(words.begin(), words.end(), isshorter);
stable_sort(words.begin(), words.end(), isshorter);

lambda表达式

lambda的目的是解决谓词参数过多的问题
可以忽略参数列表和返回类型,如果函数体只是一个return语句则可推断出返回类型,否则为void。因此必要时要使用尾置返回类型。lambda不能有默认参数。
捕获列表只用于局部非静态变量,可以直接使用局部静态变量和在它所在函数体之外声明的名字。

#include <iostream> 
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
void elimDups(vector<string> & words) {
sort(words.begin(), words.end());
auto end_unique = unique(words.begin(), words.end());//返回不重复区域之后一个元素的迭代器
words.erase(end_unique, words.end());
}
void biggies(vector<string> words, int sz) {
elimDups(words);
stable_sort(words.begin(), words.end(), [](const string & s1, const string & s2) {
return s1.size() < s2.size();
});
auto wc = find_if(words.begin(), words.end(), [sz](const string & s) {
return s.size() >= sz;
});//find_if只接受一元谓词
for_each(wc, words.end(), [](const string & s) {
cout << s << " ";
});
}
int main() {
vector<string> vec;
vec.push_back("haa");
vec.push_back("dada");
vec.push_back("feifei");
vec.push_back("feifei");
vec.push_back("heihei");
vec.push_back("hi");
vec.push_back("leila");
biggies(vec, 5);
return 0;
}

lambda捕获

当定义一个lambda时即生成一个类和该类的一个对象,参数为类对象的数据成员并在创建时被初始化。
参数是在创建时被拷贝而不是调用时拷贝。
当以引用方式捕获变量时必须保证lambda执行时变量是存在的,函数返回lambda时不能有一个局部变量的引用。尽量避免捕获指针或引用。
可以用=或&来隐式捕获,混用的话第一个必须是两者之一,后面的必须是单独指出的相反的那一个。
[v1]()mutable{ return v1++};//值捕获需要加mutable才能修改值,引用则不用

参数绑定

使用头文件functional中包含的bind函数,同时要使用命名空间using namespace std::placeholders

    bool check_size(const string & s, int sz) {
return s.size() >= sz;
}
auto wc = find_if(words.begin(), words.end(),bind(check_size, _1, sz));

绑定引用参数

for_each(words.begin(), words.end(), bind(print, ref(os), _1, ''));//cref保存const引用的类