STL算法

107 阅读3分钟

我正在参加「掘金·启航计划」

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++中函数名代替不了函数入口地址,所以要把这个函数名myPrintIntptr_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集合的差集