lambda与算法模板学习总结
来源:互联网 发布:念奴娇东方朔知乎 编辑:程序博客网 时间:2024/06/14 07:53
简要介绍 lambda拉姆达表达式
1、规则: [](入参表){函数的执行体;}
[](){} 类似一个匿名函数,没有函数名
2、lambda表达式中可以有返回值也可以没有返回值
示例代码的其他声明
class COdd{public: bool operator() (int x) { return x & 1; }};// 我们可以将 operator() 整体看做一个函数名,类似于下面的 IsOddclass 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
- lambda与算法模板学习总结
- 算法--简单排序算法总结与模板
- Lambda 表达式学习总结
- lambda 与def 的区别&lambda 学习
- Python:lambda表达式学习总结
- 数据结构与算法学习总结
- 数学算法模板总结
- 【km算法模板+总结】
- LCA 离线算法 tarjan 总结 与模板题
- Java基础学习总结(69)——匿名内部类与Lambda表达式
- JAVA8学习总结——函数式编程与lambda表达式
- lambda学习总结(c++ primer 5th)
- python学习总结---lambda匿名函数
- C#泛型委托与Lambda总结
- 【数据结构与算法分析】第一章学习总结
- JavaScript数据结构与算法学习总结--链表
- 数据结构与算法学习总结-数据结构基础
- Smarty模板学习总结
- Python scrapy 爬取拉勾网招聘信息
- Python常用数据类型方法调用
- 解决Android studio 3.0 apt插件问题
- linux 安装库 编译提示-lcrypto 无法链接,缺少 crypto 库
- ./utserver: error while loading shared libraries: libcrypto.so.0.9.8: cannot open shared object file
- lambda与算法模板学习总结
- 查询优化技术概念
- 关于C语言feof()函数判断文件结尾的问题分析
- 杭电ACM OJ 1032 The 3n + 1 problem 数据很弱,但是也需要思考一个方向
- 错误: 编码GBK的不可映射字符
- 前端使用bower+grunt-wiredep自动引入js和css
- 【分布式架构之旅】Redis入门
- 深度学习概论
- 718. Maximum Length of Repeated Subarray