【问题标题】:How to merge multiple sorted ranges in c++?如何在 C++ 中合并多个排序范围?
【发布时间】:2019-01-27 19:31:23
【问题描述】:

std::merge 对两个排序范围执行合并操作。我有 N (>>2) 个排序范围,我想将它们合并到一个排序范围中。

显而易见的方法是使用std::merge N-1 次。我想知道 C++ 标准库中是否有更好的算法。

【问题讨论】:

  • std::reduce 在二进制操作为std::merge 的范围上操作可能是您正在寻找的。但它需要一些包装器,因为 std::merge 不只有两个参数。
  • 考虑一下进行 N 路合并与多个精心选择的 2 路合并的性能影响。如需更多信息,请查看您的库的 std::list::sort 实现。

标签: c++ merge array-algorithms


【解决方案1】:

如果我们假设每个范围的大小大致相同并且总共有 M 个项目,那么 std::sort 将在 O(M log M) 时间内为您提供正确的答案,而对于简单的重复合并则为 O(M^2)。我觉得正确的答案是将整个范围一分为二并在树中调用std::merge。如果我们假设每个范围的大小大致相同并且它们是连续的并且我们有一系列迭代器指向它们,我认为这是正确的方法:https://godbolt.org/z/GudjnM

// In-place merge multiple contiguous ranges.
// Could probably get better cache coherency
// if it merged lazily (depth-first traversal
// rather than breadth-first).
template <typename IterIter>
void multi_inplace_merge(const IterIter begbeg, IterIter endend) {
    while (std::distance(begbeg, endend) >= 3) { // There's work to do.
        auto output = begbeg; // We'll overwrite with the new ranges.
        auto it = begbeg;
        for (; it != endend && it + 1 != endend; it += 2) {
            if (it + 2 != endend) { // There's something to merge.
                std::inplace_merge(it[0], it[1], it[2]);
                *output = it[0];
                ++output;
                *output = it[2];
                ++output;
            } else {
                *output = it[1];
                ++output;           
            }
        }
        endend = output;
    }
}

例如

    std::vector<int> x = {1, 10, 100,   0, 9,  -1,5, 1000, 10000, 9999999};
    std::vector<decltype(x)::iterator> its = 
      {x.begin(), 
       x.begin() + 3, 
       x.begin() + 5, 
       x.end()};
    multi_inplace_merge(its.begin(), its.end());
    for (auto y : x) {
        std::cout << y << ", ";
    }
    std::cout << std::endl;

生产

-1, 0, 1, 5, 9, 10, 100, 1000, 10000, 9999999, 

【讨论】:

    猜你喜欢
    • 2015-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-18
    • 1970-01-01
    • 2021-02-24
    相关资源
    最近更新 更多