C++常见容器泛型算法

一、只读算法

find

按顺序查找。
前两个参数表示元素范围的迭代器,第三个参数是我们要查找的值。它返回第一个等于给定值的元素的迭代器。如果范围中无匹配元素,则find返回第二个参数来表示搜索失败。
执行步骤如下:

  1. 访问序列中的首元素。
  2. 比较此元素与我们要查找的值。
  3. 如果此元素与我们要查找的值匹配,find返回标识此元素的值
  4. 否则,find前进到下一个元素,重复执行步骤2和3。
  5. 如果到达序列尾,find应停止。
  6. 如果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定义了+运算符,因此我们可以利用accumulatevector中的所有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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值