【问题标题】:Efficient median calculation for small dataset in C++C++中小数据集的高效中值计算
【发布时间】:2023-03-05 22:00:01
【问题描述】:

我有很多(数十万,m)组双打 d,~5-10(n,constant small)长。这些双打基本上是随机分布的。我需要得到每组的中位数:因为 m 非常大,我们需要很快地计算出中位数......虽然这些组非常小,所以我认为这将在选择如何做时发挥重要作用中位数。我知道我可以使用nth_element 通过选择算法获得 O(n) 中的中位数,我知道我不会在复杂性上击败它。但是,由于常数 n 很小,我可能正在寻找开销最小的方法。

我找到了很多不同的方法来做中位数(下),但如果有人知道在这里使用的“正确”方法,我只是好奇。

Min max heaps(O(n) 构建时间,持续访问,可能开销太大)

This question from 2010 可能已经过时了(新的 STL/Boost 代码可能已经实现了这些东西),也更关注时间复杂度而不是开销。

【问题讨论】:

  • 他们是std::sets 还是doubles?
  • 如今,以任何合理的标准衡量,“数十万”都不是“很多”。如果你有几十万个 5-10 个双精度元组,那么算法就无关紧要了。一个粗略的 Python 脚本遍历行,进行完整排序并打印中间元素应该在几秒钟内完成。
  • 您知道nth_element 在您的设置中的执行速度有多快吗?你需要快多少倍?
  • nth_element 可能会在下面执行基于 QSort 的第 k 个统计算法。任何使用堆等都意味着分配额外的空间,这本身可能已经增加了超出您所能承受的开销。我会说基准nth_element,你不会得到太多。
  • @MadScienceDreams 关于N(m) 是常量n 的附加信息(您有lottsa-lists,但它们都是n 元素长;这在问题中并不明显,因为-声明)很重要。您可以根据该大小选择可能展开的算法。

标签: c++ median


【解决方案1】:

这可能无法很好地适应您的数据大小,但它是我找到的代码 sn-p(不记得在哪里)并在我的图像处理函数中使用以获得 9 个无符号字符像素的中位数。

// optimised median search on 9 values
#define PIX_SWAP(a, b) { unsigned char uTemp = (a); (a) = (b); (b) = uTemp; }
#define PIX_SORT(a, b) { if ((a) > (b)) PIX_SWAP((a), (b)); }

unsigned char GetMedian9(unsigned char *pNine)
{
    // nb - this is theoretically the fastest way to get the median of 9 values
    PIX_SORT(pNine[1], pNine[2]); PIX_SORT(pNine[4], pNine[5]); PIX_SORT(pNine[7], pNine[8]); 
    PIX_SORT(pNine[0], pNine[1]); PIX_SORT(pNine[3], pNine[4]); PIX_SORT(pNine[6], pNine[7]); 
    PIX_SORT(pNine[1], pNine[2]); PIX_SORT(pNine[4], pNine[5]); PIX_SORT(pNine[7], pNine[8]); 
    PIX_SORT(pNine[0], pNine[3]); PIX_SORT(pNine[5], pNine[8]); PIX_SORT(pNine[4], pNine[7]); 
    PIX_SORT(pNine[3], pNine[6]); PIX_SORT(pNine[1], pNine[4]); PIX_SORT(pNine[2], pNine[5]); 
    PIX_SORT(pNine[4], pNine[7]); PIX_SORT(pNine[4], pNine[2]); PIX_SORT(pNine[6], pNine[4]); 
    PIX_SORT(pNine[4], pNine[2]); return(pNine[4]);
}

#undef PIX_SWAP
#undef PIX_SORT

EDIT - 好的,它也被引用了in this answer too

【讨论】:

  • 这不是 nth_element 的作用吗?
  • @MadScienceDreams - 如果是这样,那么我看不出你能做得更好。不过可能值得进行一些分析。你需要exact中位数吗?有一些算法可以提供可能更快的近似值。
  • 大约可能没问题,特别是如果我对正确中位数的概率有一定的了解...我现在开始搜索“近似中位数”,但是你有什么快速搜索的种子吗?
  • 不,我偶然发现了许多“近似中位数”算法,但我需要精确。还发现了一个不错的图像恒定时间中值滤波器 - 即与窗口大小无关,但我们对此不感兴趣。
【解决方案2】:

如果它是 std::set(你没有回答 BoBTFish)那么它已经被排序了。因此,您将通过迭代到 n/2 来获得中位数,这总是更好或等于 O(n),通常应该是 O(ld n)。第 n 个元素在这里没有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-15
    • 2014-01-02
    • 1970-01-01
    • 2015-05-04
    • 2010-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多