【问题标题】:Is there a way to do nth_element together with copy of data?有没有办法将 nth_element 与数据副本一起做?
【发布时间】:2020-01-09 15:51:36
【问题描述】:

我希望从 C++ 中的浮点数组中计算中值:

float Median( FloatArray const * constFloatArray )
{
    FloatArray    scratch = FloatArray( *constFloatArray );
    int64_t const size    = scratch.GetWidth() * scratch.GetHeight();
    int64_t const mid     = size / 2;

    std::nth_element( scratch.begin(), scratch.begin() + mid, scratch.end() );

    return scratch[ mid ];
}

FloatArray 包含一个常规的 C++ 浮点数数组。

我正在使用std::nth_element,但想知道是否有像nth_element 这样的设施可以处理const 数据?现在,我正在制作一个副本,然后在扔掉副本之前做nth_element。如果const 数据没有类似nth_element 的内容,是否有更有效的方法使用复制步骤来计​​算信息,从而避免潜在的额外 O(n) 循环?也许性能影响可以忽略不计?我的数组大小可能在 20 亿左右。

【问题讨论】:

  • 您可能想研究一些不会修改源代码的其他算法,例如:stackoverflow.com/questions/10930732/…
  • 您也许可以调整nth_element 算法以同时复制元素(stackoverflow.com/questions/29145520/…),但我怀疑它会明显更快。如果您进行性能比较,看看结果会很有趣。
  • 在不使用 o(n) 额外空间改变输入的情况下选择中位数是不可能的,因此它不是非修改算法的自然候选者;副本也没有明显的用途。

标签: c++ constants nth-element


【解决方案1】:

我不确定它是否会更有效,但您可以使用std::partial_sort_copy 节省一半的复制。我们可以使用std::partial_sort_copy 仅将一半数据复制到一个新数组中,然后它会将其排序到该数组中。然后,您需要做的就是为奇数个元素获取最后一个元素,或者为偶数个元素获取最后两个元素的平均值。使用看起来像的向量

int main() 
{
    std::vector<int> v{5, 6, 4, 3, 2, 6, 7, 9, 3, 10};
    std::vector<int> r(v.size() / 2 + 1);
    std::partial_sort_copy(v.begin(), v.end(), r.begin(), r.end());
    if (r.size() % 2)
        std::cout << r.back();
    else
        std::cout << (r[r.size() - 1] + r[r.size() - 2]) / 2.0;
}

【讨论】:

  • 据我了解,nth_element 出乎意料地只有 O(n),所以不会进行排序会将其撞到 O(n*log(n))?
  • @WilliamKF 实际上是O(Nlog(N/2)),但是是的,它在算法上更复杂。虽然它确实节省了一半的空间和一半的副本,所以它可以做得更好,但这是你需要在你的数据集上进行基准测试的东西。
  • @NathanOliver:/2 在 O 内部没有区别。
猜你喜欢
  • 2017-12-11
  • 2018-04-27
  • 2018-03-15
  • 2016-11-01
  • 1970-01-01
  • 2018-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多