zoukankan      html  css  js  c++  java
  • 第10章 泛型算法

    10.1概述

    大多数算法定义在头文件<algorithm>中,另外在<numeric>中定义了一组数值泛型算法。

    一般来说,算法不直接操作容器,而是使用迭代器访问容器中的元素,但是在对元素进行比较的时候,会依赖于元素的类型:

    auto result = find(vec.cbegin(), vec.cend(), val);

    如果没有查找到结果,将会返回第二个参数

    10.2泛型算法

    *泛型算法一般不会改变容器的大小,只有在使用inserter(插入器)的时候可能会改变

     

    类型1:求和算法,始末位置&结果类型

    accumulate

    类型2:比较序列,始末位置1&起始位置2

    equal

    类型3:赋值,始末位置&值

    fill、fill_n

    back_inserter插入迭代器

    每次给一个插入迭代器赋值,会首先调用push_back方法,将给定元素值添加到容器中。

    vector<int> vec;

    auto it = back_inserter(vec);

    *it = 42;

    fill_n(it, 10, 0);

    类型4:拷贝算法,始末位置&起始位置

    copy

    replace_copy

    *_copy//很多方法都提供了拷贝的版本

    类型5排序算法与唯一值算法混合

    sort(vec.begin(), vec.end() );

    auto end_unique = unique(vec.begin(), vec.end() );

    //算法不能操作容器,所以容器中重复的元素并没有删除,而是放在了end_unique之后

    Vec.erase(end_unique, vec.end() );

    10.3定制操作

    对于算法中使用到的比较,我们可以自定义比较的方法,尤其是对于那些没有提供比较运算符重载的类型。

    10.3.1向算法传递函数

    以函数作为参数,这个参数就是一个谓词

    根据谓词接受参数的多少,在标准库算法中,分为一元谓词和二元谓词

    10.3.2lambda表达式

    形式

    [capture list] (parameter list) mutable -> return type {function body}

    其中必须包含捕获列表和函数体。

    捕获列表表示function body可以使用的外部变量。

    mutable表示函数体中可以改变值捕获变量的值,但是因为是值传递,并不能反映到外部对应的变量中。对于引用捕获,能否改变值在与传递的是否是const类型,与mutable无关。

    注意

    使用lambda表达式时,编译器会创建一个对应的类,并初始化这个类的对象进行使用。其中捕获列表中的内容会是这个类的成员变量,初始化对象时使用捕获列表中的变量对成员初始化。

    捕获列表可以为空,并且分为引用捕获(&)和值捕获。可以使用隐式引用捕获“[&]”,隐式值捕获“[=]”,部分值捕获“[&, a]”,部分引用捕获“[=, &a]”。

    在含有判断语句的函数体中,如果return全部在判断语句中,则return type的类型推断将会为void,所以应该尽可能的书写return type。

    10.3.4参数绑定

    形式

    auto newCallable = bind(callable, arg_list)

    arg_list是按照callable参数的顺序完整书写的,其中使用_n表示newCallable中参数的位置。

    例如:auto newFunc = bind(func, b, _2, c, ref(a), _1)。func有5个参数,newFunc有两个参数,在绑定中newFunc的两个参数分别对应func的第5和2个参数。

    使用bind,需要包含functional头文件。

    使用参数占位符,需要使用std::placeholders命名空间。

    使用引用参数绑定,需要使用ref函数

    #include <iostream>

    #include <vector>

    #include <algorithm>

    #include <functional>

    using namespace std;

    using namespace std::placeholders;

    int main() {

             // your code goes here

             vector<int> ab={22,44,55,77};

             auto v = find_if(ab.begin(),ab.end(),

             bind([=](int a,int b) -> bool {return a==b;},_1,55));

             cout<<*(v)<<endl;

             return 0;

    }

    10.4再探迭代器

    插入迭代器

        back_inserter

        front_inserter

        inserter

    instream迭代器

        istream_iterator

        ostream_iterator

    反向迭代器

        可以使用反向迭代器的.base()方法得到常规迭代器

    10.5泛型算法结构

    泛型算法对容器的要求通常有:可读、可写、可删除、可增加、随机访问。所以每个算法都对所操作的迭代器有一定的要求。

    10.5.1对应有5类迭代器

    输入迭代器input iterator

    输出迭代器output iterator

    前向迭代器forward iterator

    双向迭代器bidirectional iterator

    随机访问迭代器rand-access iterator

    10.5.2算法的形参模式

    alg(beg, end, other args)

    alg(beg, end, dest, other args)

    alg(beg, end, beg2, other args)

    alg(beg, end, beg2, end2, other args)

    接受单个目标迭代器的算法

    dest参数表示算法可以写入目的位置的迭代器,算法假定可以向这个位置中写入元素。因此,比较常见的是dest表示一个插入迭代器或者ostream_iterator。

    接受第二个输入序列的算法

    接受beg2和end2,表示第二个输入迭代器的范围

    只接受beg2,则是第二个输入范围的首元素,并假设beg2开始的范围至少与第一个一样。

    10.5.3算法命名规范

    一些算法使用重载的形式传递一个谓词

    unique(beg, end)//默认使用==进行比较,并确定唯一性

    unique(beg, end, comp)//使用传递的谓词comp进行比较

    _if版本的算法

    find(beg, end, val)//val第一次出现的位置

    find_if(beg, end, pred)//使pred为真的位置

    区分拷贝元素的版本和不拷贝元素的版本

    reverse(beg, end)

    reverse(beg, end, dest)

    10.6特定容器算法

    链表类型list和forward_list定义了特有的sort, merge, remove, reverse, unique,因为其链表结构不同于其他容器,其数据不能够随机访问,因此只能使用其特有的算法。通用的算法不能够使用这些容器,或者对于这些容器来讲是低效率的。

    另外,链表类型定义了splice成员,用于在两个链表中移动元素。

  • 相关阅读:
    将十进制的颜色制转换成ARGB
    HTTPS从认识到线上实战全记录
    如何从零开始对接第三方登录(Java版):QQ登录和微博登录
    JS弹出下载对话框以及实现常见文件类型的下载
    【干货】Chrome插件(扩展)开发全攻略
    Lucene5.5.4入门以及基于Lucene实现博客搜索功能
    ReactNative与NativeScript对比报告
    JavaScript常见原生DOM操作API总结
    JS获取剪贴板图片之后的格式选择与压缩问题
    详细记录一下网站备案经过,备案真的很简单
  • 原文地址:https://www.cnblogs.com/qiusuo/p/4801082.html
Copyright © 2011-2022 走看看