一、只读算法
find
按顺序查找。
前两个参数表示元素范围的迭代器,第三个参数是我们要查找的值。它返回第一个等于给定值的元素的迭代器。如果范围中无匹配元素,则find返回第二个参数来表示搜索失败。
执行步骤如下:
- 访问序列中的首元素。
- 比较此元素与我们要查找的值。
- 如果此元素与我们要查找的值匹配,find返回标识此元素的值
- 否则,find前进到下一个元素,重复执行步骤2和3。
- 如果到达序列尾,find应停止。
- 如果find到达序列结尾,它应该返回一个指出元素未找到的值。此值和步骤3返回的值必须有相容的类型。
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
int main(){
string str = "it is an example";
char val = 'a';
auto result = find(str.begin(),str.end(),val);
cout << "The value " << val << (result == str.end() ? " is not present" : " is present") << endl;
}
find_if
find_if(_InputIterator __first, _InputIterator __last,_Predicate __pred)
find_if() 的第三个参数是一个 lambda 表达式的谓词。一个lambda表达式表示一个可调用的代码单元,其具有一个返回类型、一个参数列表和一个函数体。但与函数不同,lambda可能定义在函数内部,表达式具有如下形式:
[capture list] (parameter list) -> return type {function body}
其中capture list
(捕获列表)是一个lambda所在函数中定义的局部变量。
lambda必须使用尾置返回(用于函数返回类型的自动推导,一般用于返回类型比较复杂,或者需要通过模板参数(亦或其它表达式)来推导返回类型的情况,通常会结合 decltype (用来在编译时推导出一个表达式的类型。)一起使用,本质上算是一种语法糖,在函数定义的参数列表右侧添加 ->ReturnType
来代表函数返回类型,将通常放置函数返回类型的地方使用 auto
代替。语法格式:auto FuncName(ArgsList) -> ReturnType { }
)
//找出words中长度大于3的元素个数
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main(){
//初始化words使其无重复元素且按长度和字典序排好序
vector<string> words = {"ab","cde","deg","rtyu"};
//获取一个迭代器,指向第一个满足size >= sz的元素
vector<string>::size_type sz = 3;
auto result = find_if(words.begin(), words.end(),
[sz](const string &a){ return a.size() >= sz; });
//计算满足size >= sz的元素的数目
auto count = words.end() - result;
//输出结果为3
cout << count << endl;
}
accumulate
进行求和。
该函数定义在numeric
头文件中,接受三个参数,前两个指出了需要求和的范围,第三个是和的初值。该函数将第三个参数作为求和的起点,因此要求元素的类型加到第三个参数上的操作必须是可行的。
#include <numeric>
#include <iostream>
using namespace std;
int main(){
int vec[] = {1,2,3,4,5};
int sum = accumulate(begin(vec), end(vec), 0);
cout << sum << endl;
}
由于string定义了+运算符,因此我们可以利用accumulate将vector中的所有string元素连接起来。
#include <numeric>
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<string> vec = {"bar", "foo", "the"};
auto sum = accumulate(vec.begin(), vec.end(), string(""));
cout << sum << endl;
}
equal
确定两个序列是否保存相同的值。
此函数接受三个参数。前两个表示第一个序列的范围,第三个表示第二个序列的首元素。它将第一个序列的每个元素与第二个序列中对应的元素进行比较,如果所有对应元素都相等则返回true,否则返回false。它假设第二个序列至少和第一个序列一样长。
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
int main(){
string s1 = "zxcvxmm";
string s2 = "zxcvxmm";
auto result = equal(s1.begin(),s1.end(),s2.begin());
cout << result << endl;
}
二、写容器元素的算法
fill
fill接受一对迭代器表示要修改的范围,接受一个值作为第三个参数,将给定的值赋给输入序列的每个元素。
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
int main(){
vector<int> vec = {1, 2, 3, 4, 5};
for (auto it : vec){
cout << it;
}
cout << endl;
fill(vec.begin(), vec.end(), 0);//将每个元素重置为0
for (auto it : vec){
cout << it;
}
cout << endl;
}
fill_n
fill_n接受一个单迭代器,一个计数值和一个值。它将给定值赋予迭代器指向的元素开始的由计数值指定的元素个数。
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
int main(){
vector<int> vec = {1, 2, 3, 4, 5};
for (auto it : vec){
cout << it;
}
cout << endl;
fill_n(vec.begin(), vec.size(), 0);//将每个元素重置为0
for (auto it : vec){
cout << it;
}
cout << endl;
}
注意不要在空容器上使用fill_n
。
copy
向目地位置迭代器指向的输出序列中的元素写入数据。此函数接受3个迭代器,前两个表示一个输入范围,第三个表示目的序列的起始位置,将输入范围中的元素拷贝到目的序列中。传递给copy的目的序列至少要包含与输入序列一样多的元素。
#include <algorithm>
#include <iostream>
using namespace std;
int main(){
int vec1[] = {0,1,2,3,4,5,6,7,8,9};
int vec2[sizeof(vec1)/sizeof(*vec1)];
auto ret = copy(begin(vec1), end(vec1), vec2);//将vec1的内容拷贝给vec2
for (auto it : vec2){
cout << it;
}
cout << endl;
}
copy返回的是其目的位置迭代器(递增后)的值。即ret指向拷贝到vec2的尾元素之后的位置。
replace
replace读入一个序列,并将其中所有等于给定值的元素都改为另一个值。该函数接受四个参数:前两个是迭代器,表示输入序列,后两个一个是搜索的值,一个是新值。
#include <algorithm>
#include <iostream>
using namespace std;
int main(){
int vec[] = {0,1,2,3,4,5,6,7,8,9};
replace(begin(vec), end(vec), 3, 2);//将vec中为3的元素改为2
for (auto it : vec){
cout << it;
}
cout << endl;
}
若希望保持原序列不变,可以调用replace_copy
,此函数接受额外第三个迭代器参数,指出调整后的序列的保存位置。
#include <algorithm>
#include <iostream>
using namespace std;
int main(){
int vec1[] = {0,1,2,3,4,5,6,7,8,9};
int vec2[sizeof(vec1)/sizeof(*vec1)];
replace_copy(begin(vec1), end(vec1), vec2, 3, 2);
for(auto it : vec2){
cout << it;
}
cout << endl;
}
三、重排容器元素的算法
sort unique
sort接受两个迭代器,表示要排序的元素范围。
unique也接受两个迭代器,表示处理的范围,unique并不真正删除任何元素,它只是覆盖相邻的重复元素,使得不重复元素出现在序列开始部分。
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main(){
vector<string> v2 = {"bar", "foo", "the","foo","bar"};
//按字典排序v2,以便查找重复单词
sort(v2.begin(), v2.end());
//unique重排输入范围,使得每个单词只出现一次
//排列在范围的前部,返回指向不重复区域之后的一个位置的迭代器
auto end_unique = unique(v2.begin(), v2.end());
//例如此处的输出为foo
cout << *end_unique << endl;
//使用向量操作erase删除重复单词
v2.erase(end_unique,v2.end());
for (auto it : v2){
cout << it;
}
cout << endl;
}
stable_sort
此函数多接受一个参数,该参数是一个谓词。谓词是一个可调用的表达式,其返回结果是一个能用作条件的值。用该谓词代替一般sort的<来比较元素。
这是一种稳定排序算法,维持相等元素的原有顺序,在该例子中维持相等长度单词的字典序。
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
//比较函数,用来按长度排序单词
bool isShorter(const string &s1, const string &s2){
return s1.size() < s2.size();
}
int main(){
vector<string> v2 = {"foo", "bar", "foo", "th"};
//按字典排序v2
sort(v2.begin(), v2.end());
//按长度重新排序,长度相同的单词维持字典序
stable_sort(v2.begin(), v2.end(),isShorter);
//输出为thbarfoofoo
for (auto it : v2){
cout << it;
}
cout << endl;
}