std::merge
和std::inplace_merge
在复杂性和结果方面的区别是什么,它在两个连续的范围内执行时,元素都是不同的? (我不是母语为英语的人,我不确定是否清楚地了解“inplace”意味着什么)
答案 0 :(得分:23)
查看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
必须输出到与输入范围不同的范围
它还表示以下调用(对于某些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));
例如。
有趣的是,this reference表明范围不应重叠(刚好在返回值部分之上),这似乎比必要的更严格,因为这意味着两个输入范围也不应重叠。此外,在数据竞赛部分,它非常明确地指出只能访问两个输入范围,所以这个有点人为的(人工)示例:
std::merge(a.begin(), a.end(), a.begin(), a.end(), b.begin());
据此,是违法的,但我不相信。这些引用都不是标准,不幸的是我没有它的副本来引用自己,但也许有访问权限的人可以验证这些要求。
修改强>:
有了从TemplateRex到标准草案的有用指针,我现在可以说
N3797 25.4.4 [alg.merge]
2 需要:[...]结果范围不得与任何一个重叠 原始范围。
这确切地证实了我的意思。