C++ 泛型算法详解(上)

您所在的位置:网站首页 accumulate函数头文件 C++ 泛型算法详解(上)

C++ 泛型算法详解(上)

2023-03-17 01:06| 来源: 网络整理| 查看: 265

泛型算法

文章目录 1. 概述: 2. 初识泛型算法 只读算法 可写算法 重排容器元素的算法 消除重复的单词 简单总结 3. 定制操作 3.1 向算法传递函数 3.2 lambda表达式 lamdba的结构 向lamdba传递参数 使用捕获列表 调用find_if 查找 for_each 打印算法 简单总结: 3.3 lamdba的捕获与返回 值捕获 引用捕获 隐式捕获 可变lamdba 指定lamdba返回类型 简单总结: 3.4 参数绑定 bind函数 绑定函数的参数 bind的参数

1. 概述:

泛型算法:实现了一些经典算法的公共接口,可以用于不同类型的元素和容器类型。

include < algorithm > 头文件

find 算法:用来查找第一个符合条件的元素,用两个迭代器作为范围。

find不仅可以查找容器,也可以适用于内置数组

只要有一个迭代器可用来访问元素,find就完全不依赖于容器类型(或数组)。

利用find查找某个元素 int ia[]{ 1,2,3,4,5,6 }; int val = 5; int* p = find(begin(ia), end(ia), val); cout 1,2,3,4,5,6 }; cout 1,2,3,4,5,6}; //可以是不用类型的容器 auto fg = equal(cbegin(a), cend(a), cbegin(b)); cout 1.5,2,3,4,5,6,7,8,5,10,11,5,5,5 }; list b; //可以是不同类型的容器 replace_copy(cbegin(a), cend(a), back_inserter(b), 5, 666); 重排容器元素的算法 消除重复的单词

使用vector读取一系列string的单词,如何消除vector容器中重复的string单词?

sort函数:给指定范围的元素排序。

unique函数: "消除"重复的单词,注意必须要是相邻的,但是并未完全消除,可以理解为把相邻的元素只留下一个,剩下的都放在了尾部,然后unique返回一个指向没有重复元素的下一个位置的迭代器。

erase函数: 彻底删除元素,接受一个范围,删除元素。

示例:sort ---->> unique ---->>erase

vector a; string temp; while (cin >> temp) { a.push_back(temp); } //先排序 sort(begin(a), end(a)); //再消除 auto it=unique(begin(a), end(a)); //最后删除 a.erase(it, a.end());

程序在无重复的情况下也是正常的

一个图例: 分别是sort unique erase的情况C++ 泛型算法详解(上)_迭代器

简单总结

本节函数:find()搜索,accmulate()求和,equal()相等判断,fill()、fill_n()赋值,back_insert()插入操作,copy()拷贝,sort()排序,unique()重排并消重复

3. 定制操作 3.1 向算法传递函数

谓词的概念:谓词是一个可调用的表达式,返回结果是一个能用做条件的值。

一元谓词:接受单一参数

二元谓词:接受两个参数

示例:我们使用单词的长度来排序sort函数,而不是字母的顺序(sort接受二元谓词)

sort(begin(a), end(a), isShorter); //排序函数 bool isShorter(const string& s1, const string& s2) { return s1.size() "abcde","oiodwa","cenjd","66","yt","hhg","envisenvesv","uiytr" }; auto it=partition(words.begin(), words.end(), isfive); for (auto iter = words.cbegin(); iter != it; ++iter) { cout //删除重复元素,按照字典序排序 elimDups(words); //按长度再排序 stable_sort(words.begin(), words.end(), isShorter); //接下来该怎么做??? }

我们可以使用find_if函数:接受一个范围和一个一元谓词,但是,当我们传递给一个谓词字符串和长度时,它是二元谓词,我们无法编写传递两个参数的谓词给find_if函数。

lamdba的结构

我们可以向一个算法传递一个任意类别的可调用对象。

lamdba表达式:表示一个可调用的代码单元,可以理解为一个未命名的内联函数。

lamdba表达式具有返回类型,参数列表,函数体;但与函数不同,lamdba可以定义在函数内部。

lamdba结构: [局部变量](参数列表)->返回类型 {函数体}

可以忽略参数列表和返回类型,但是一定要包含捕获列表(通常为空)和函数体。

定义:f 为一个可调用对象,返回42,但是他不接受任何参数。

auto f = [] {return 42; };

调用:

cout return a.size() > b.size(); }); 使用捕获列表

传递给find_if一个可调用表达式: sz为某一个指定的长度,判断字符串长度是否大于sz。

[sz](const string& s){return s.size()>sz;};

捕获列表[sz],指明了lamdba即将会使用这些变量,只有捕获才可以在函数体使用!

调用find_if 查找

获取一个 迭代器,指向第一个满足长度大于指定长度的字符串的位置:

auto it=find_if(words.begin(),words.end(),[sz](const string& s){return s.size()>sz;});

返回了下一个位置的迭代器,然后再计算从现在在末尾有多少个元素(已经排序完毕!).

auto count=words.end()-it; //返回个数 for_each 打印算法

​ 捕获列表为空,调用cout打印,it此时指向符合条件的第一个元素,打印到末尾的元素。

for_each(it,words.end(),[](const string& s){coutreturn s.size() >= sz; }); //获取元素个数 auto count = words.end() - it; //打印 for_each(it, words.end(), [](const string& s) {cout return a.size() return s.size() >=sz; }); //返回第一个不符合条件的位置 //获取元素个数 auto count = itNotfir - words.begin(); cout return a; }; //创建时捕获 a = 10; //更改不会改变已经捕获完的lamdba cout // os隐式捕获:引用捕获方式 c显式捕获:值捕获方式 for_each(words.begin(), words.end(), [&, c](const string& s) {os return ++v1; }; v1 = 0; cout -1,-2,-3,-4,-5,-6,9,8,7,4,-5 }; transform(begin(ar), end(ar), begin(ar), [](int& i) {return (i if (i "woaini" }; auto b1 = check6(s); //调用check_size(s,6) find_if(words.begin(), words.end(), bind(check_size, _1, sz));

命名空间:using std::placeholders::_1。

bind的参数 auto g=bind(func,a,b,_2,c,_1);

生成了一个新的的可调用对象g,g包含两个参数,分别是第3和第5个;func原调用对象的第一,第二,第四个参数分别被绑定到a,b,c上。

bind调用会使:g( _1, _2)映射为(a,b,__2,c, __1);

绑定引用参数:

ostream& print(ostream & os, const string & s, char c) { return os


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3