我正在参加「掘金·启航计划」
1. 函数对象(仿函数)
仿函数是一个类不是一个函数,仿函数重载了()操作符使得它可以像函数一样调用。示例如下:
class Print{
public:
void operator()(char* str){
cout << str << endl;
}
};
void test(){
Print ob;
ob("hello world");
Print()("hello world")
}
2. 谓词
返回bool类型的普通函数或仿函数都叫谓词。 下面示例用的普通函数:
bool greaterThan30(int value){
return value > 30;
}
3. 内建函数对象
(内建)STL提供了一些函数对象。内部提供了算数类函数对象、运算类函数对象、逻辑运算类函数对象。
算术类函数对象 除了negate是一元运算,其他都是二元运算
template<class T> T plus<T> //加法仿函数
template<class T> T minute<T> //减法仿函数
template<class T> T multiplies<T> //乘法仿函数
template<class T> T divides<T> //除法仿函数
template<class T> T modulus<T> //取模仿函数
template<class T> T negate<T> //取反仿函数
关系类运算函数对象 每一种都是二元运算
template<class T> bool equal_to<T> //等于
template<class T> bool not_equal__to<T> //不等于
template<class T> bool greater<T> //大于
template<class T> bool greater_equal<T> //大于等于
template<class T> bool less<T> //小于
template<class T> bool less_equal<T> //小于等于
逻辑运算类函数对象 not为一元运算,其余为二元运算
template<class T> bool logical_and<T> //逻辑与
template<class T> bool logical_or<T> //逻辑或
template<class T> bool logical_not<T> //逻辑非
4. 适配器
适配器 为算法提供接口
函数对象适配器
下面实现的是所有的值加200
void test(){
vector<int> v1;
v1.push_back(10);
v1.push_back(50);
v1.push_back(30);
v1.push_back(90);
v1.push_back(70);
}
第一步:bind2nd或bind1st绑定参数
对于for_each(v1.begin(),v1.end(),bind2nd(PrintInt(),200))bind2nd就是把200绑定到PrintInt中重载()的第二个参数,bind1st是绑定到第一个参数
//for_each只有三个参数,但是我们有四个参数,所以得绑定一下
for_each(v1.begin(),v1.end(),bind2nd(PrintInt(),200))
第二步:公共继承binary_function参数萃取
第三步:const修饰operator()
class PrintInt:public binary_function<int, int, void>{
public:
//第三步:const修饰operator()
void operator()(int val, int tmp) const{
cout << val + tmp << " ";
}
};
函数指针适配器ptr_fun
普通函数作为适配器
void myPrintInt(int value, int tmp){
cout << "value=" << value <<" tmp=" << tmp << endl;
}
void test(){
//...
for_each(v1.begin(),v1.end(),bind2nd(ptr_fun(myPrintInt),100));
}
在c++中函数名代替不了函数入口地址,所以要把这个函数名myPrintInt用ptr_fun函数指针操作一下,目的是得到这个函数的入口地址。
成员函数作为适配器 用mem_fun_ref
class Data{
//...
void printInt(int tmp){//...}
}
for_each(v1.begin(),v1.end(),bind2nd(mem_fun_ref(&Data::printInt),100));
取反适配器 not1就是取反,如下代码,只有一个绑定参数30,所以是not1
for_each(v1.begin(),v1.end(),not1(bind2nd(greater<int>(),30)));
二元取反
lambda表达式
[&](int val){
//函数内容
}
[]里面什么都不写,lambda不能识别外部数据。[=]lambda能对外部数据读操作[&]lambda能对外部数据读写操作
sort(v1.begin(), v1.end(), not2(greater<int>()));
这里not2是因为比较是需要两个参数的。
5. 常用遍历算法
for_each遍历算法
//beg、end开始结束,_callback回调
for_each(iterator beg, iterator end, _callback);
transfrom算法 将指定容器区间元素搬运到另一个容器中。注意:transform不会给目标容器分配内存,所以需要我们提前分配好内存。
//beg1\end1是开始结束迭代器;
//beg2目标开始迭代器
//_callback回调函数或者函数对象
transform(iterator beg1, iterator end1, iterator beg2, _callback)
6.常用查找算法
find算法 从某个容器中找某个元素
find_if算法 从某个容器中找符合条件的元素
adjacent_find算法查找相邻重复元素,返回相邻元素的第一个位置的迭代器
binary_search算法 容器必须是有序的,二分查找算法,返回的是找没找到
count算法
count_if算法
7.常用排序算法
merge算法容器元素合并,并存储到另一容器中(将两个容器合并到第三个容器中),两个容器必须是有序的。
sort算法排序算法
random_shuffle算法打乱容器中的元素,可以打乱指定范围内的元素
reverse算法反转指定范围的元素。
8.常用拷贝替换算法
copy算法将容器指定范围的元素拷到另一容器中
replace算法将容器指定范围的旧元素修改为新元素
replace_if算法将容器内指定范围满足条件的元素替换为新元素
swap算法互换两个容器的元素.
9.常用算术生成算法
accumulate算法计算容器元素累计总和
fill算法向容器中添加元素
10.常用集合算法
set_intersection算法求两个set的交集
set_union算法求两个set的并集
set_difference算法求两个set集合的差集