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

时间:2014-02-07 09:45:45

标签: c++ algorithm c++11 stl stl-algorithm

std::mergestd::inplace_merge在复杂性和结果方面的区别是什么,它在两个连续的范围内执行时,元素都是不同的? (我不是母语为英语的人,我不确定是否清楚地了解“inplace”意味着什么)

1 个答案:

答案 0 :(得分:23)

查看std::mergestd::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 需要:[...]结果范围不得与任何一个重叠   原始范围。

这确切地证实了我的意思。