c++ - 前面有 `std::partial_sum` 的 `0` 最干净的方法是什么?

标签 c++ std stdvector prefix-sum

在C++中,有一个函数std::partial_sum来计算前缀和。代码

#include <iostream>
#include <vector>
#include <iterator>
#include <numeric>

int main() {
    std::vector<int> a = {1, 2, 3, 4, 5};
    std::partial_sum(a.begin(), a.end(), a.begin());
    return 0;
}

将把 a 覆盖为 1 3 6 10 15,这是预期的。

但是,大多数情况下我想使用前缀和,我想要前面有一个 0 来表示“空和”,这样我就可以使用 a[2] - a[0 ] 查询前两个元素的总和。 (这允许我使用一个简单的嵌套 for 循环来查找所有子数组的总和)。有没有办法用 std::partial_sum 函数来实现它?我不知道这是否可能,因为输出大小将是输入大小 + 1。

注意:我并不是在寻找预先改变 a 内容或类型的方法。

如果a的大小是一个问题:

#include <iostream>
#include <vector>
#include <iterator>
#include <numeric>

int main() {
    std::vector<int> a = {1, 2, 3, 4, 5, -1};
    std::partial_sum(a.begin(), a.end() - 1, a.begin());
    return 0;
}

这样的东西也适合我。

最佳答案

Is there a way to achieve it with the std::partial_sum function?

只需在调用 std::partial_sum 之前向输出迭代器写入 0。应该小心,因为输出比输入大,并且这不会就地工作,因为它在读取第一个输入之前写入第一个输出。

template<class InputIt, class OutputIt>
constexpr OutputIt my_partial_sum(InputIt first, InputIt last, OutputIt d_first)
{
    *d_first++ = typename std::iterator_traits<InputIt>::value_type{};
    return std::partial_sum(first, last, d_first);
}

如果您希望能够就地完成此操作,您可以调整 possible implementation std::partial_sum 进一步

template<class InputIt, class OutputIt>
constexpr OutputIt partial_sum(InputIt first, InputIt last, OutputIt d_first)
{
    using value_type = typename std::iterator_traits<InputIt>::value_type;

    if (first == last) {
        *d_first++ = value_type{};
        return d_first;
    }

    value_type sum{};
    value_type next = *first;

    *d_first++ = sum;
 
    while (++first != last) {
       next = *first;
       sum = std::move(sum) + next;
       *d_first++ = sum;
    }
    return d_first;
}

但我认为更简单的方法是在容器前添加 0。

template <typename Container>
void my_partial_sum(Container& c) {
    c.emplace(c.begin());
    std::partial_sum(c.begin(), std::prev(c.end()), c.begin());
}

关于c++ - 前面有 `std::partial_sum` 的 `0` 最干净的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68994302/

相关文章:

c++ - 使用标准句柄后如何将背景颜色恢复为以前的颜色

c++ - Matlab API 使用 STL 容器从 C++ 读取 .mat 文件

c++ - Win32 API : how to read the serial, 或如果不是数据则在超时内退出

c++ - 为什么 std::set<>::find 返回一个常量?

c++ - Qt : is good in a c++ class to have a widget field not declared as a pointer

c++ - 将 shared_ptr vector 填充到 Base & Derived 对象的函数模板

c++ - vector push_back 调用 copy_constructor 不止一次?

c++ - 从文件名中获取目录名

Android ndk 问题 socket 和 std 问题

C++ vector 异常处理 : Which one is the better way of throwing out_of_range() and why?