std::merge 和 std::inplace_merge 之间的区别?

Difference between std::merge and std::inplace_merge?

本文关键字:std merge 区别 inplace 之间      更新时间:2023-10-16

std::mergestd::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必须输出到与任一输入范围不同的范围。
这也意味着以下调用(对于某些RandomAccessContainera):

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要求: [...]所得范围不得与以下任何一项重叠 原始范围。

这恰恰证实了我所说的。