该算法在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这样的操作。
-
参考