std库学习②:accumulate

该算法在numeric头文件中定义。

首先来看一个例子:

//定义了一个整型vector数组
vector<int> vec {2, 0, 12, 3, 5, 0, 2, 7, 0, 8};

按标准版的accumulate来使用,如下:

std::accumulate(vec.begin(),vec.end(),35);

上面的代码语句意思是:将数组从开头起至结尾的每一个元素进行相加,最后再加上35,返回结果。

同样的,我们定义一个string类型的数组:

此语句的意思是将该string数组从头至尾依次进行连接,并输出结果:

666onetwothreefourfivesixseveneightnineten

下面是accumulate的函数定义:

// 1. 无op
template <class InputIterator, class T>
   T accumulate (InputIterator first, InputIterator last, T init);

// 2. 有op
template <class InputIterator, class T, class BinaryOperation>
   T accumulate (InputIterator first, InputIterator last, T init,
                 BinaryOperation binary_op);
  • 无运算操作

【总结】

accumulate接收了三个参数,使用迭代器来标识开始和结束区间,即第一个参数为开始区间,第二个参数为结束区间,而第三个参数至关重要,它不仅仅是累加的初值,还规定了该函数返回值的类型。这就要求迭代器元素的类型要与第三个参数的类型一致,亦或者是能够转化(类似于double--->int,会损失精度)。

  • 有运算操作

先来看看一个例子;

std::vector<int> values {2, 0, 12, 3, 5, 0, 2, 7, 0, 8};
int min {3};
auto sum = std::accumulate(std::begin(values), std::end(values), 0, [min] (int sum, int v)
{
    if(v < min)
        return sum;
    return sum + v;
});
std::cout << "The sum of the elements greater than " << min-1<<"is " << sum << std::endl;  // 35

上面这个例子的运算是自动过滤掉小于3的数组元素,然后进行自定义的运算操作,即累加。

再来看看一个关于乘法的例子:

std::vector<int> values {2, 3, 5, 7, 11, 13};
auto product = std::accumulate(std::begin(values), std::end(values), 1, std::multiplies<int>()); // 30030

为数值元素定义的乘法运算函数会生成元素的乘积,只要初值为 1。实现浮点元素除法的函数会生成元素乘积的倒数,只要初值为 1。

【总结】

对于有运算操作的accumulate使用,我们第一个参数与第二个参数与无运算操作的accumulate一样,均是迭代器的起始与结束位置,第三个是我们进行运算的初始值,最后一个参数是我们自定义的操作,通常可以通过定义一个函数或者是使用lamda式子来进行定义;并且该函数不仅仅限于累加操作,累乘累除均可以,只要自定义。

 

  • 更多示例

#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
struct Functor
{
    int operator () (int i, int j)
    {
        //cout<<"i = "<<i<<endl;
        //cout<<"j = "<<j<<endl;
        return i + j;
    }
};

int main(){
    vector<int> vi{ 1, 5, 3 };
    auto product = accumulate(vi.begin(), vi.end(), 0, Functor());
    cout<<product<<endl;
}

上述代码表示初始化一个整型数组,将每个元素放入函数对象中进行运算,并且在结构体中重载了“()”的使用方法,每次运算结果作为参数i进行传入,下一个读取的元素作为j传入,然后进行运行。

int res = accumulate(vi.begin(), vi.end(), 
                        0, 
                        bind(plus<int>(), _1, 
                            bind(multiplies<int>(), _2, 2)
                        )
                    );

使用bind函数,可以实现init + v[i] * 2这样的操作。

  • 参考

【C++ STL应用与实现】86: 如何使用std::accumulate

C++ accumulate函数用法详解

发布了90 篇原创文章 · 获赞 6 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_37160123/article/details/93845663
std