查看std::merge 和std::inplace_merge 的引用,您会发现以下复杂性:
对于std::merge:
至多 std::distance(first1, last1) +
std::distance(first2, last2) - 1 次比较。
对于std::inplace_merge:
如果有足够的额外内存可用,则进行 N-1 次比较,
否则 N·log(N) 其中 N = std::distance(first, last)。
if enough additional memory is available 有一个非常具体的含义,来自该页面上的注释:
此函数尝试分配一个临时缓冲区,通常通过调用
std::get_temporary_buffer。如果分配失败,效率越低
算法被选中。
std::get_temporary_buffer 动态分配内存(了解您是否想在紧密循环中使用std::inplace_merge 或限制内存需求很重要)。
最后,参考页面没有提到这一点(编辑:cppreference已根据下面的评论更新),但在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));
例如。
有趣的是,this reference 声明范围不得重叠(刚好在返回值部分上方),这似乎比必要的更严格,因为这意味着两个输入范围也不得重叠。此外,在数据竞争部分中,它非常清楚地说明了两个输入范围只能访问,所以这个稍微做作(人为)的例子:
std::merge(a.begin(), a.end(), a.begin(), a.end(), b.begin());
据此将是非法的,但我不相信。这些参考资料都不是标准,遗憾的是我自己没有参考资料的副本,但也许有访问权限的人可以验证这些要求。
编辑:
借助 TemplateRex 对标准草案的有用指针,我现在可以说
N379725.4.4 [alg.merge]
2 要求:[...]结果范围不得与任何一个重叠
原始范围。
这完全证实了我所说的。