reduce vs accumulate 笔记(C++算法竞赛向)

📌 基本概念对比

特性std::accumulate (C++98)std::reduce (C++17)
头文件<numeric><numeric>
执行顺序严格从左到右无序(可能并行)
初始值必须提供可选(无初始值时用默认构造)
并行支持不支持支持并行执行
运算要求仅需可结合需可结合+可交换

🚀 典型用法

1. accumulate 基础用法

vector<int> v{1, 2, 3, 4};

// 累加求和(必须提供初始值)
int sum = accumulate(v.begin(), v.end(), 0); 

// 累乘(初始值1)
int product = accumulate(v.begin(), v.end(), 1, multiplies<>());

2. reduce 基础用法

vector<int> v{1, 2, 3, 4};

// 并行累加(无初始值)
int sum = reduce(execution::par, v.begin(), v.end());

// 带初始值的累乘
int product = reduce(v.begin(), v.end(), 1, multiplies<>());

🔍 关键差异详解

1. 执行顺序

// accumulate 严格顺序执行
accumulate(v.begin(), v.end(), 0, [](int a, int b) {
    cout << a << "+" << b << endl; // 1+2 → 3+3 → 6+4
    return a + b;
});

// reduce 可能乱序执行(打印顺序不确定)
reduce(execution::par, v.begin(), v.end(), 0, plus<>());

2. 初始值处理

vector<float> v{1.1, 2.2, 3.3};

// accumulate 必须显式指定类型
auto sum1 = accumulate(v.begin(), v.end(), 0); // 错误!得到int 6

// reduce 可自动推导类型
auto sum2 = reduce(v.begin(), v.end()); // 正确:6.6 (float)

⚠️ 注意事项

accumulate 的坑

vector<string> strs{"a", "b", "c"};

// 注意初始值类型!
auto wrong = accumulate(strs.begin(), strs.end(), ""); // 错误!const char* 无+操作
auto correct = accumulate(strs.begin(), strs.end(), string(""));

reduce 的限制

// 非交换运算会导致未定义行为
auto bad = reduce(v.begin(), v.end(), 1, [](int a, int b) {
    return a - b; // 错误!减法不可交换
});

🏆 竞赛应用场景

优先使用 accumulate 的情况

  1. 需要确定计算顺序时
  2. 处理非交换运算(如字符串拼接)
    vector<string> words{"Hello", " ", "World"};
    string sentence = accumulate(words.begin(), words.end(), string(""));
    

优先使用 reduce 的情况

  1. 大规模数值计算(1e6+元素)
    vector<double> big_data(1e7, 0.1);
    double total = reduce(execution::par, big_data.begin(), big_data.end());
    
  2. 需要自动类型推导时

📊 性能对比(1e7次加法)

方法时间(ms)
accumulate25
reduce (单线程)24
reduce (并行)8

💡 进阶技巧

自定义运算

// 求向量模长的平方和
vector<Point> points{{1,2}, {3,4}};
double sum_sq = accumulate(points.begin(), points.end(), 0.0, 
    [](double acc, Point p) { return acc + p.x*p.x + p.y*p.y; });

并行reduce最佳实践

// 确保数据足够大(>1e5)
vector<int> data(1e6);
iota(data.begin(), data.end(), 0);

// 并行执行(需包含<execution>)
int sum = reduce(execution::par_unseq, 
                data.begin(), 
                data.end());

📌 竞赛建议:默认使用accumulate保证正确性,大数据量时切换为并行reduce

// 模板宏定义
#define FAST_SUM(v) (v.size()>1e5 ? \
    reduce(execution::par, v.begin(), v.end()) : \
    accumulate(v.begin(), v.end(), 0))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值