【问题标题】:Difference between std::merge and std::inplace_merge?std::merge 和 std::inplace_merge 之间的区别?
【发布时间】:2014-03-04 15:49:35
【问题描述】:

std::merge 和std::inplace_merge 在两个具有不同元素的连续范围上执行时,在复杂性和结果方面有什么区别? (我不是以英语为母语的人,我不确定是否清楚地理解“就地”是什么意思)

【问题讨论】:

  • 就地基本上意味着没有为新的输出范围永久分配内存。 (在幕后,会有一个临时缓冲区,但这对用户来说是无法观察到的)。

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


【解决方案1】:

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

这完全证实了我所说的。

【讨论】:

  • 为什么不通过引用the draft Standard 来使这个答案更准确? (提示:寻找 [alg.merge])
  • @TemplateRex 谢谢,我不知道在哪里可以找到标准,更不用说引用它了(即使它只是一个草稿)。
  • +1 now :-) Pro-tip from Stephan T. Lavavaj 关于如何引用标准(见该评论的底部)。
  • 您认为在大多数实现中临时缓冲区将是范围的总大小还是只是其中的一小部分?
  • 重叠在 cppreference 中被提及。
猜你喜欢
  • 2013-01-18
  • 2012-04-25
  • 2015-07-21
  • 2012-10-27
  • 1970-01-01
  • 1970-01-01
  • 2014-09-17
  • 2021-07-10
  • 1970-01-01
相关资源
最近更新 更多