C++回顾之泛型算法

泛型算法介绍

泛型算法大多数是独立于任何特定的容器的,定义在头文件algorithmnumeric中,算法不直接操作容器,而是遍历由两个迭代器指定的一个元素范围。

泛型算法种类

只读算法

find(vec.cbegin(),vec.cend(),0);//返回迭代器 
count(vec.cbegin(),vec.cend(),0);//返回给定值在序列中出现的次数
int sum = accumulate(vec.cbegin(),vec.cend(),0);//sum设置为vec中元素的和,定义在numeric中,和的初值为0
string sum = accumulate(vec.cbegin(),vec.cend(),string(""));//string才有加法运算,char * 类型没有,字符串的初值为空
equal(roster1.cbegin(), roster1.cend(),roster2.cbegin());//可以用来比较不同容器内的元素,只要能用==比较就可以,第二个序列至少与第一个一样长!如果两个序列中的元素完全一样则相等。

写容器元素的算法

    fill(vec.begin(), vec.end(), 0);//将每个元素重置为0,注意不能超出原有vec的size,否则会出错
    fill_n(vec.begin(), vec.size(), 0); 

    auto ret = copy(begin(a1), end(a1), a2);//拷贝到新的数组中去,返回的是尾元素之后的位置
    replace(list.begin(), list.end(), 0, 42);//把所有0的值取代为42
    replace_copy(list.begin(), list.end(), back_inserter(vec), 0,42);//取代后拷贝到新的容器中

size是指出vector存有元素的个数,capacity是指出现有vector可以存放多少元素

插入迭代器
    #include <iterator> 
    vector<int> vec;
    auto it = back_inserter(vec);//返回一个插入迭代器
    *it = 42;
    *it = 50;
    cout << vec.size() << endl;//结果为2,调用一次相当于一次push_back;
    fill_n(back_inserter(vec), 10, 0);
    cout << vec.size() << endl;//结果为12!

重排容器

删除序列中重复元素的程序:

#include <iostream> 
#include <string>
#include <algorithm>
#include <vector> 
using namespace std;
void elimDups(vector<string> & words) {
    sort(words.begin(), words.end());//排序
    auto end_unique = unique(words.begin(), words.end());//不重复元素出现在开始部分,返回不重复区域之后一个元素的迭代器
    words.erase(end_unique, words.end());//删除掉多余的
}
int main() {
    vector<string> vec;
    vec.push_back("e");
    vec.push_back("b");
    vec.push_back("c");
    vec.push_back("c");
    vec.push_back("d");
    vec.push_back("d");
    vec.push_back("a");
    elimDups(vec);
    cout << vec.size() << endl;
    return 0;
}

swap操作

操作于容器(除了array,string)迭代器,指针,引用仍指向原来元素值,操作于string会失效,操作于array迭代器,指针,引用指向原来元素位置但值改变啦!(303页)
swap(vec1,vec2);

定制操作

自定义函数,然后向算法传递参数取代原有的比较函数(如<运算符)

bool isshorter(const string &  s1, const string & s2) {
    return s1.size() < s2.size();
} 
sort(words.begin(), words.end(), isshorter);
// 保证等长元素之间的字典序
stable_sort(words.begin(), words.end(), isshorter);

lambda表达式

lambda的目的是解决谓词参数过多的问题
可以忽略参数列表和返回类型,如果函数体只是一个return语句则可推断出返回类型,否则为void。因此必要时要使用尾置返回类型。lambda不能有默认参数。
捕获列表只用于局部非静态变量,可以直接使用局部静态变量和在它所在函数体之外声明的名字。

#include <iostream> 
#include <string>
#include <algorithm>
#include <vector> 
using namespace std;
void elimDups(vector<string> & words) {
    sort(words.begin(), words.end());
    auto end_unique = unique(words.begin(), words.end());//返回不重复区域之后一个元素的迭代器
    words.erase(end_unique, words.end());
}
void biggies(vector<string> words, int sz) {
    elimDups(words);
    stable_sort(words.begin(), words.end(), [](const string & s1, const string & s2) {
        return s1.size() < s2.size();
    });
    auto wc = find_if(words.begin(), words.end(), [sz](const string & s) {
        return s.size() >= sz;
    });//find_if只接受一元谓词
    for_each(wc, words.end(), [](const string & s) {
        cout << s << " ";
    });
}
int main() {
    vector<string> vec;
    vec.push_back("haa");
    vec.push_back("dada");
    vec.push_back("feifei");
    vec.push_back("feifei");
    vec.push_back("heihei");
    vec.push_back("hi");
    vec.push_back("leila");
    biggies(vec, 5);
    return 0;
}

lambda捕获

当定义一个lambda时即生成一个类和该类的一个对象,捕获参数为类对象的数据成员并在创建时被初始化。

捕获参数是在创建时被拷贝而不是调用时拷贝。因此捕获之后修改值不会影响lambda函数的执行。

当以引用方式捕获变量时必须保证lambda执行时变量是存在的,函数返回lambda时不能有一个局部变量的引用。尽量避免捕获指针或引用。

可以用=或&来隐式捕获,混用的话第一个必须是两者之一,后面的必须是单独指出的相反的那一个。

值捕获需要加mutable才能修改值,引用则不用

void fun() {
    int a = 5;
    auto f = [a]() mutable{ return ++a; };
    cout << f() << endl; //6
    cout << f() << endl; //7
}

参数绑定

也是用来解决谓词参数过多的问题。可以将bind看成一个通用的函数适配器。使用头文件functional中包含的bind函数,同时要使用命名空间using namespace std::placeholders _n是占位符,表示调用绑定后函数传入的参数的位置。

    bool check_size(const string & s, int sz) {
    return s.size() >= sz;
    }
    auto wc = find_if(words.begin(), words.end(),bind(check_size, _1, sz));

绑定引用参数

for_each(words.begin(), words.end(), bind(print, ref(os), _1, ''));//cref保存const引用的类
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值