当std::merge
和std::inplace_merge
在两个连续的范围内执行时,元素都不同时,它在复杂性和结果方面有什么区别?(我的母语不是英语,我不确定是否清楚地理解"就地"的含义)
查看 std::merge 和 std::inplace_merge 的引用,您会看到以下复杂性:
对于std::merge
:
最多标准::d(首页1,末页1) + std::d istance(first2, last2) - 1 比较。
对于std::inplace_merge
:
如果有足够的额外内存可用,则正好 N-1 比较, 否则 N·log(N) 其中 N = std::d istance(first, last)。
该if enough additional memory is available
具有非常具体的含义,来自该页面上的注释:
此函数尝试分配临时缓冲区,通常通过调用 标准::get_temporary_buffer。如果分配失败,效率越低 选择算法。
std::get_temporary_buffer
动态分配内存(这对于了解是否要在紧密循环中使用std::inplace_merge
或具有受限的内存要求非常重要)。
最后,参考页面没有提到这一点(编辑:cpp首选项已根据下面的评论进行了更新),但std::merge
我认为d_first
不能重叠[first1, last1)
或[first2, last2)
。 这意味着std::merge
必须输出到与任一输入范围不同的范围。
这也意味着以下调用(对于某些RandomAccessContainer
a
):
std::inplace_merge(a.begin(), a.begin() + n, a.end());
不等同于:
std::merge(a.begin(), a.begin() + n,
a.begin() + n, a.end(), a.begin());
因为如果您从中读取,则无法输出到a
。 您将需要:
decltype(a) b;
std::merge(a.begin(), a.begin() + n,
a.begin() + n, a.end(),
std::back_inserter(b));
例如。
有趣的是,此引用指出范围不应重叠(就在返回值部分上方),这似乎比必要的更严格,因为这意味着两个输入范围也不应重叠。 此外,在数据竞赛部分,它非常清楚地指出仅访问两个输入范围,因此这个稍微人为(人为)的示例:
std::merge(a.begin(), a.end(), a.begin(), a.end(), b.begin());
根据这一点是非法的,但我不相信。 这些引用都不是标准,不幸的是,我没有它的副本来引用自己,但也许有访问权限的人可以验证这些要求。
编辑:
有了从TemplateRex到标准草案的有用指针,我现在可以说
N3797 25.4.4 [合并]
2要求: [...]所得范围不得与以下任何一项重叠 原始范围。
这恰恰证实了我所说的。