给定vector<T> vec{...}
,假设T是数字类型之一,提取其最小值,最大值和中位数的最佳方法是什么?我知道std::nth_element
和std::minmax_element
,但是如果一个接一个地调用,它们似乎会做多余的工作。
到目前为止,我想到的最好的主意是只一次叫std :: nth_element 3次。但这仍然需要3N比较,对吗?有什么方法可以重用先前迭代中完成的部分排序吗?
答案 0 :(得分:11)
使用std::nth_element
进行分区,得出中位数,然后在左半部分std::min_element
,在右半部分std::max_element
进行
如果您需要更快的速度,请根据std::nth_element
推出自己的版本。
答案 1 :(得分:3)
另一种选择是为std::nth_element
指定自定义比较,以捕获最小值和最大值。最终可能会进行更多的比较和分支,因此这在某些特定的硬件上可能会变慢,这可能取决于您缓存了多少数据等。因此,一如既往,请基准测试一下,但是对于非空的vector
a
,该技术看起来像这样:
int min = a[0], max = a[0];
std::nth_element(a.begin(), a.begin() + n, a.end(),
[&](int lhs, int rhs) {
min = std::min(min, std::min(lhs, rhs));
max = std::max(max, std::max(lhs, rhs));
return lhs < rhs;
});
在我的(〜10yo i5-660)HTPC上使用GCC 7.4并在100到1000之间随机分配100万个int
时,nth_element
花费的时间少了36% / max比较。