分享下 STL Numeric 库的函数

作者: | 更新日期:

只有 5 个函数,也许可以提高编码效率。

本文首发于公众号:天空的代码世界,微信号:tiankonguse

之前在文章《分享下 STL algorithm 库我常用的函数》中分享了我部分常用的函数。

有人评论还有 accumulate 求和函数比较常用。
其实写文章时我也留意到没写 accumulate 这个函数。
所以我提前去确认了下,发现这个函数在 Numeric 库中。

Numeric 库只有 5 个函数,现在想想其实有几个也有用的,所以今天专门介绍一下。

对于 iota 函数,go 语言的同学应该会比较熟悉。

因为在 go 语言中,枚举值可以通过 iota 来设置自动递增。

  1. const (
  2. Zero = iota // 0
  3. One // 1
  4. Two // 2
  5. )

cpp 中,可以通过迭代器来依次把递增序列储存起来。

  1. iota(nums.begin(), nums.end(), val)
  2. // 等价与
  3. for(auto& v: nums){
  4. v = val;
  5. val = val + 1;
  6. }

第二个函数 accumulate 可以方便的区间求和。

  1. accumulate(nums.begin(), nums.end(), 0L);
  2. // 等价与
  3. sum = 0L;
  4. for(auto v: nums){
  5. sum = sum + v;
  6. }

进阶用法:求和操作自定义。

  1. accumulate(nums.begin(), nums.end(), 0L, [](auto& sum, auto& v){
  2. return sum + v * v;
  3. });
  4. // 等价与
  5. sum = 0L;
  6. for(auto v: nums){
  7. sum = sum + v * v;
  8. }

第三个函数 inner_product 用处不大,因为内积这个操作在算法比赛中不常用,需要的时候自己实现比较好。

  1. inner_product(a.begin(), a.end(), b.begin(), 0L);
  2. // 等价与
  3. sum = 0;
  4. bi = 0;
  5. for(auto av: a){
  6. sum = sum + av * b[bi];
  7. bi++;
  8. }

进阶操作:求和操作与内积操作自定义。

  1. inner_product(a.begin(), a.end(), b.begin(), 0L, [](auto& sum, auto &v){
  2. return sum + v;
  3. }, [](auto& a, auto& b){
  4. return srqt(a * a + b * b);
  5. });
  6. // 等价与
  7. sum = 0;
  8. bi = 0;
  9. for(auto av: a){
  10. sum = sum + srqt(av * av + b[bi] * b[bi]) ;
  11. bi++;
  12. }

第四个函数 partial_sum 其实蛮有用的,因为我们经常需要求前缀和。

  1. partial_sum(a.begin(), a.end(), preSum.begin());
  2. // 等价与
  3. sum = 0;
  4. for(auto v: a){
  5. sum += v;
  6. preSum.push_back(sum);
  7. }

进阶操作:前缀积。

  1. partial_sum(a.begin(), a.end(), preSum.begin(), [](auto& pre, auto& v){
  2. return pre * v;
  3. });
  4. // 等价与
  5. sum = 1;
  6. for(auto v: a){
  7. sum = sum * v;
  8. preSum.push_back(sum);
  9. }

第五个函数是 adjacent_difference 求相邻差,算法上也很少使用。

  1. adjacent_difference(a.begin(), a.end(), dis.begin());
  2. // 等价与
  3. int pre = 0;
  4. for(auto v: a){
  5. dis.push_back(v - pre);
  6. pre = v;
  7. }

进阶操作:相邻元素的操作可以封装为函数,例如相邻和。

  1. adjacent_difference(a.begin(), a.end(), dis.begin(), [](auto&a, auto&b){
  2. return a + b;
  3. });
  4. // 等价与
  5. int pre = 0;
  6. for(auto v: a){
  7. dis.push_back(v + pre);
  8. pre = v;
  9. }

看完 Numeric 库的五个函数,发现有三个可以在算法上可能会用到。

第一个是区间递增,使用场景是给一个大小为 n 的数组分配 1 到 n 的值。
第二个是区间求和,这个也是最常用的。
第三个是前缀和,不少算法都需要求前缀和的。

如果要使用高阶函数,即自定义操作函数,还不如自己循环事项相关的功能,会更灵活。

面对 Numeric 库的这几个函数,你怎么看呢?
觉得封装的有意义吗?

加油,算法人。

《完》

-EOF-

本文公众号:天空的代码世界
个人微信号:tiankonguse
公众号ID:tiankonguse-code

本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。

关注公众号,接收最新消息

tiankonguse +
穿越