lambda与算法模板学习总结

简要介绍 lambda拉姆达表达式
1、规则: [](入参表){函数的执行体;}
[](){} 类似一个匿名函数,没有函数名
2、lambda表达式中可以有返回值也可以没有返回值

示例代码的其他声明

class COdd
{
public:
    bool operator() (int x)
    {
        return x & 1;
    }
};// 我们可以将 operator() 整体看做一个函数名,类似于下面的 IsOdd

class AAA
{
private:
    int x;
    int y;
public:
    AAA() :x(0), y(0) {}
    AAA(int a, int b) :x(a), y(b) {}
    friend ostream& operator<< (ostream& os, const AAA& A)
    {
        os << "(" << A.x << ", " << A.y << ")";
        return os;
    }
    bool operator ==(const AAA& A)
    {
        if (this->x == A.GetX() && this->y == A.GetY())
            return true;
        return false;
    }
    int GetX() const { return x; };
    int GetY() const { return y; };
};

bool IsOdd(int x)
{
    return x & 1;
}

lambda与算法模板

算法模板的头文件:#include <algorithm>
运行结果截图在文章末尾
1、all_of、any_of、none_of
all_of:判断某个区间的元素,是否【所有】都满足某个条件
any_of :判断某个区间的元素,是否【存在】都满足某个条件
none_of :判断某个区间的元素,是否【所有】都不满足某个条件

    vector<AAA> aVec;
    vector<AAA>::iterator itAAA;
    deque<AAA> aDeq;

    vector<int> iVec;
    vector<int>::iterator itVec;
    deque<int> iDeq;
    deque<int>::iterator itDeq;

    iVec.assign({ 1,2,3,4,5,6,8,9,14 });
    bool bRet = false;
    bRet = all_of(iVec.begin(), iVec.begin() + 5, COdd());//判断是否都满足偶数
    bRet = all_of(iVec.begin(), iVec.begin() + 5, IsOdd);
    bRet = all_of(iVec.begin(), iVec.begin() + 5, [](int x) {return x & 1; });  // [](int x) {return x & 1; } 为一个匿名函数,没有函数
    bRet = any_of(iVec.begin(), iVec.end(), [](int x) {return !(x & 1); });//判断是否存在偶数
    bRet = none_of(iVec.begin(), iVec.end(), [](int x) {return x > 10; });// 判断是否都不满足 > 10

2、for_each
for_each:对迭代器内的元素一次做某个操作

    cout << "\nfor_each输出元素:";
    for_each(iVec.begin(), iVec.end(), [](int x) {cout << x << " "; });
    cout << endl;

3、find、find_if、find_if_not、find_end、find_first_of
find:查找等于某个元素的值(满足条件的第一个值),返回迭代器
注:这里会调用元素的 == 比较,如果为对象需要重载 == 运算符
find_if:查找【第一个满足】某个元素的值,返回迭代器
find_if_not:查找【第一个不满足】某个元素的值,返回迭代器
find_end:查找子序列,返回最后一个子序列的起始位置,没有查找到,返回 end()
注:!!!不是查找最后一个满足的元素
find_first_of:在一个容器内,查找第一个出现在另一个容器里的元素
注:!!!不是查找第一个子序列
adjacent_find:在序列中,查找第一对相邻且相等元素的位置,返回前面元素的迭代器,没有则返回end()

是否返回迭代器,根据 第三个参数,也就是 lambda 表达式 是否返回true

    aVec.assign({ AAA(),AAA(1,2),AAA(2,3), AAA(3,4),AAA(4,4) });
    itAAA = find(aVec.begin(), aVec.end(), AAA(1, 2));
    itAAA = find_if(aVec.begin(), aVec.end(), [](AAA A) {return A.GetX() == 2; });
    itAAA = find_if_not(aVec.begin(), aVec.end(), [](AAA A) {return A.GetX() == 0; });
    // find_end 在iVec中查找最后一个iDeq子序列,返回起始位置迭代器
    iVec.assign({ 1,2,3,4,5,2,3,6,2,3,7 });
    iDeq.assign({ 2,3 });// 2,3子序列
    itVec = find_end(iVec.begin(), iVec.end(), iDeq.begin(), iDeq.end());
    cout << "\n最后一个子序列的位置:";
    for_each(itVec, iVec.end(), [](int x) {cout << x << " "; });
    cout << endl;
    // find_first_of 
    iVec.assign({ 1,2,3,4,5 });
    iDeq.assign({ 8,7,6,5,4,3 });
    itVec = find_first_of(iVec.begin(), iVec.end(), iDeq.begin(), iDeq.end());
    cout << "\niVec中,第一个存在于iDeq中的元素:" << *itVec << endl;
    itDeq = find_first_of(iDeq.begin(), iDeq.end(), iVec.begin(), iVec.end());
    cout << "iDeq中,第一个存在于iVec中的元素:" << *itDeq << endl;
    // adjacent_find
    iVec.assign({ 1,2,3,4,5,5,4,3,2,1 });
    itVec = adjacent_find(iVec.begin(), iVec.end());// 默认 == 运算符比较
    cout << "第一对相邻相等的元素:" << *itVec << "," << *(itVec + 1) << endl;

    aVec.assign({ AAA(),AAA(1,2),AAA(1,4),AAA(3,4),AAA(3,4),AAA(4,5) });
    itAAA = adjacent_find(aVec.begin(), aVec.end());// 默认 == 运算符比较
    cout << "第一对相邻相等的元素:" << *itAAA << "," << *(itAAA + 1) << endl;
    itAAA = adjacent_find(aVec.begin(), aVec.end(),
        [](AAA A1, AAA A2) {return A1.GetX() == A2.GetX(); });
    cout << "第一对相邻相等的元素:" << *itAAA << "," << *(itAAA + 1) << endl;
    // 解析:为什么不使用 cout << "第一对相邻相等的元素:" << *itAAA << "," << *(++itAAA) << endl;或
    //                  cout << "第一对相邻相等的元素:" << *itAAA << "," << *(itAAA++) << endl;
    //            而使用 cout << "第一对相邻相等的元素:" << *itAAA << "," << *(itAAA+1) << endl;
    // cout 运算符,在调用的时候,会把需要输出的东西一次压栈
    // endl *(++itAAA) *itAAA -->压栈的时候就做了 ++ 运算,后面压入的*itAAA是执行了 ++ 之后的
    //itAAA = adjacent_find(aVec.begin(), aVec.end(),
    //  [](AAA A1, AAA A2) {return A1.GetX() == A2.GetX(); });
    //所以该示例中,使用 *(++itAAA)-> (1,4),(1,4)
    //                  *(itAAA++)->(1,4),(1,2)
    //                  *(itAAA+1)->(1,2),(1,4)//正确的输出方式

4、count、count_if
count:统计序列中等于某个值的元素的个数
count_if:统计序列中满足某个条件的元素个数

    iVec.assign({ 1,2,3,4,5,8,9,5,4,3,2,1 });
    int cnt = count(iVec.begin(), iVec.end(), 2);
    cout << "\niVec序列中等于2的元素的个数:" << cnt << endl;
    cnt = count_if(iVec.begin(), iVec.end(), [](int x) {return !(x & 1); });
    cout << "iVec序列中满足为偶数的元素个数:" << cnt << endl;

5、mismatch、equal、is_permutation
mismatch:比较两个序列的元素,返回第一个对不相等的元素,默认为 == 运算符比较,也可以自定义
第二个序列中只有起始位置(使用的时候,注意越界的问题)
第二个序列比第一个序列短,而第二个序列与第一个序列的前面的元素一样,就会越界
解决办法:使短的序列为第一个序列
equal:判断两个序列是否相等
第二个序列只有起始位置(和 mismatch 一样),同样有越界问题
is_permutation:长序列前面的元素和短序列的所有元素比较,如果比较的元素是一样的,只是顺序不一样,返回true,否则false

    iVec.assign({ 1,3,5,7,9,10,23,45 });
    iDeq.assign({ 1,3,5,7,8 });
    if (iVec.size() < iDeq.size())
    {
        pair<vector<int>::iterator, deque<int>::iterator> itPair;
        itPair = mismatch(iVec.begin(), iVec.end(), iDeq.begin());
        if (itPair.first == iVec.end())
            cout << "没有查找到第一对不相等的元素" << endl;
        else
            cout << "\n第一对不相等的元素:" << *itPair.first << "," << *itPair.second << endl;
    }
    else
    {
        pair<deque<int>::iterator, vector<int>::iterator> itPair;
        itPair = mismatch(iDeq.begin(), iDeq.end(), iVec.begin());
        if (itPair.first == iDeq.end())
            cout << "没有查找到第一对不相等的元素" << endl;
        else
            cout << "\n第一对不相等的元素:" << *itPair.first << "," << *itPair.second << endl;
    }

    aVec.assign({ AAA(), AAA(1, 2), AAA(3, 4), AAA(4, 5), AAA(2, 2) });
    aDeq.assign({ AAA(), AAA(1, 2), AAA(2, 4), AAA(4, 5) });
    if (aDeq.size() < aVec.size())
    {
        pair<deque<AAA>::iterator, vector<AAA>::iterator> itPair;
        itPair = mismatch(aDeq.begin(), aDeq.end(), aVec.begin(),
            [](AAA A1, AAA A2) {return (A1.GetX() == A2.GetX()) && (A1.GetY() == A2.GetY()); });
        cout << "\n第一对不相等的元素:" << *itPair.first << "," << *itPair.second << endl;
    }
    else
    {
        // ...
    }

    iVec.assign({ 1,3,5,7,9 });
    iDeq.assign({ 1,3,5,7,9,2,4,6,8 });
    if (iVec.size() < iDeq.size())
    {
        //bRet = equal(iVec.begin(), iVec.end(), iDeq.begin());
        bRet = equal(iVec.begin(), iVec.end(), iDeq.begin(), [](int a, int  b) {return a == b; });
        cout << "equals?:" << (bRet ? "Yes" : "No") << endl;
    }
    else
    {
        // ...
    }

    iVec.assign({ 1,3,5,7,9 });
    iDeq.assign({ 5,9,7,1,3,12,3,4,5 });
    if (iVec.size() < iDeq.size())
    {
        //bRet = is_permutation(iVec.begin(), iVec.end(), iDeq.begin());
        bRet = is_permutation(iVec.begin(), iVec.end(), iDeq.begin(), [](int a, int  b) {return a == b; });
        cout << "IsPermutation:" << (bRet ? "Yes" : "No") << endl;
    }
    else
    {
        bRet = is_permutation(iDeq.begin(), iDeq.end(), iVec.begin());
        cout << "IsPermutation:" << (bRet ? "Yes" : "No") << endl;
    }

6、search、search_n
search:查找第一个子序列,与find_end对应,返回子序列起始位置的迭代器
search_n:查找连续n个等于某个值的元素位置,返回起始位置的迭代器

    iVec.assign({ 1,2,3,4,5,3,4,5,6,5,6,9 });
    iDeq.assign({ 4,5 });
    //itVec = search(iVec.begin(), iVec.end(), iDeq.begin(), iDeq.end());// 默认 == 运算符
    itVec = search(iVec.begin(), iVec.end(), iDeq.begin(), iDeq.end(), [](int a, int b) {return a == b; });
    cout << "\n第一个子序列位置:";
    for_each(itVec, iVec.end(), [](int x) {cout << x << " "; });
    cout << endl;

    iVec.assign({ 1,2,2,2,3,4,4,4,5,2,2,2,7 });
    //itVec = search_n(iVec.begin(), iVec.end(), 3, 2);// 查找3个连续等于2的元素位置, 默认 == 运算符
    itVec = search_n(iVec.begin(), iVec.end(), 3, 2, [](int a, int b) {return a == b; });
    cout << "3个连续等于2的元素位置:";
    for_each(itVec, iVec.end(), [](int x) {cout << x << " "; });
    cout << endl;

7、copy、copy_n、copy_if、copy_backward
copy:把第一个序列的元素,拷贝到第二个序列
要求第二个序列足够(保证不越界)
copy_n:指定长度拷贝,拷贝第一个序列 n 个长度的元素到第二个序列
copy_if:拷贝区间中满足某个条件的元素
copy_backward:指定结束位置,从后往前拷贝

    iVec.assign({ 1,3,5,7,9 });
    iDeq.assign({ 2,4,6,8 });
    //copy(iVec.begin(), iVec.end(), iDeq.begin());// 报错,4<5, 空间不足,访问越界
    iDeq.resize(iVec.size());
    copy(iVec.begin(), iVec.end(), iDeq.begin());
    cout << "\niDeq中的元素:";
    for_each(iDeq.begin(), iDeq.end(), [](int x) {cout << x << " "; });
    cout << endl;

    iVec.assign({ 1,3,5,7,9 });
    iDeq.assign({ 2,4,6,8 });
    copy_n(iVec.begin(), 3, iDeq.begin());
    cout << "iDeq中的元素:";
    for_each(iDeq.begin(), iDeq.end(), [](int x) {cout << x << " "; });
    cout << endl;

    // 把 iVec 中所有偶数,拷贝到 iDeq 中
    iVec.assign({ 1,2,3,4,5,6,7,8,9 });
    iDeq.resize(iVec.size());
    copy_if(iVec.begin(), iVec.end(), iDeq.begin(), [](int x) {return !(x & 1); });
    cout << "iDeq中的元素:";
    for_each(iDeq.begin(), iDeq.end(), [](int x) {cout << x << " "; });
    cout << endl;

    iVec.assign({ 1,2,3,4,5,6,7 });
    iDeq.assign({ 11,22,33,44,55 });
    copy_backward(iDeq.begin(), iDeq.end(), iVec.end());
    cout << "iVec中的元素:";
    for_each(iVec.begin(), iVec.end(), [](int x) {cout << x << " "; });
    cout << endl;

8、move
move:移动元素,但是这个移动元素,源序列的元素是不变的,效果和copy一样
注:copy与move的区别:就和memmove与memcpy一样
源内存和目的内存不一样的情况下,两个函数功能一样
源内存和目的内存重合的情况下,例如:char arr[]={1,2,3,4};
memmove(arr,arr+1,3)=>arr[]={1,1,1,1}
memmcpy(arr,arr+1,3)=>arr[]={1,1,2,3}

    iVec.assign({ 1,2,3,4,5,6 });
    move(iVec.begin(), iVec.end() - 1, iVec.begin() + 1);
    cout << "\niVec中的元素:";
    for_each(iVec.begin(), iVec.end(), [](int x) {cout << x << " "; });
    cout << endl;

    iDeq.assign({ 1,2,3,4,5,6 });
    copy(iDeq.begin(), iDeq.end() - 1, iDeq.begin() + 1);
    cout << "iDeq中的元素:";
    for_each(iDeq.begin(), iDeq.end(), [](int x) {cout << x << " "; });
    cout << endl;

9、swap、iter_swap、swap_ranges
swap:交换两个元素的值(如果入参是迭代器,交换的就是迭代器的值)
iter_swap:交换两个迭代器指向的元素的值
swap_ranges:交换一段区间的元素值

    list<int> iList1({ 1,3,5,7 });
    list<int> iList2({ 2,4,6,8 });
    list<int>::iterator it1, it2;

    it1 = iList1.begin();
    it2 = iList2.begin();
    swap(it1, it2);// ==> 交换两个迭代器的值
    cout << "\nswap:" << iList2.front() << "--" << *it2 << endl;

    it1 = iList1.begin();
    it2 = iList2.begin();
    iter_swap(it1, it2);// ==> 交换两个迭代器指向的元素的值
    cout << "iter_swap:" << iList2.front() << "--" << *it2 << endl;

    iList1.assign({ 1,3,5,7,9 });
    iList2.assign({ 2,4,6,8,10 });
    swap_ranges(iList1.begin(), --iList1.end(), iList2.begin());
    for_each(iList2.begin(), iList2.end(), [](int x) {cout << x << " "; });
    cout << endl;

10、transform
transform:把一段区间的元素,做某个处理后,存入另外一个区间

    iVec.assign({ 1,3,5,7,9 });
    iDeq.resize(iVec.size());
    transform(iVec.begin(), iVec.end(), iDeq.begin(), [](int x) {return x + x; });
    cout << "\niDeq:";
    for_each(iDeq.begin(), iDeq.end(), [](int x) {cout << x << " "; });
    cout << endl;

    vector<string> sVec({ "aa","sdc","abc","werdd","rtuf" });
    iDeq.resize(sVec.size());
    transform(sVec.begin(), sVec.end(), iDeq.begin(), [](string s) {return s.length(); });
    cout << "iDeq:";
    for_each(iDeq.begin(), iDeq.end(), [](int x) {cout << x << " "; });
    cout << endl;

11、repalce、repalce_if、repalce_copy、replace_copy_if
repalce:把区间等于某个值的元素替换成另一个
repalce_if:把区间中,所有满足某个条件的元素替换成另一个
repalce_copy:把replace替换的结果存入另一个区间,源区间保存不变
replace_copy_if:把replace_if替换的结果存入另一个区间,源区间保存不变

    iVec.assign({ 1,3,5,3,9 });
    replace(iVec.begin(), iVec.end(), 3, 9);// 把3替换成9

    iVec.assign({ 1,2,3,4,5,6,7 });
    replace_if(iVec.begin(), iVec.end(), [](int x) {return x & 1; }, 0);// 满足条件的替换为 0

    iDeq.resize(iVec.size());
    replace_copy(iVec.begin(), iVec.end(), iDeq.begin(), 1, 2);

12、fill、fill_n
fill:把某个区间填为某个值
fill_n:指定区间起始位置,填充 n 个元素为某个值(类似memset)

    iVec.assign({ 1,3,5,7,9 });
    fill(iVec.begin(), iVec.begin() + 3, 0);//=> 0 0 0 7 9
    fill_n(iVec.begin(), 3, 1);//=> 1 1 1 7 9

13、generate
generate:按照某个规则生成元素,一次赋值给区间的元素

    iVec.resize(10);
    generate(iVec.begin(), iVec.end(), []()// 填写 10 个偶数
    {
        static int i = 0;
        i += 2;
        return i;
    });
    cout << "\niVec:";
    for_each(iVec.begin(), iVec.end(), [](int x) {cout << x << " "; });
    cout << endl;

运行截图:
这里写图片描述
有些是没有输出的,写到后面越来越懒,没写输出直接查看内存了
示例源码:https://pan.baidu.com/s/1mhXwr6w

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值