C++ 什么';这是提取最小值、最大值和最大值的最有效方法;向量中值
给定一个向量向量{…}假设T是一种数值类型,提取其最小值、最大值和中值的最佳方法是什么?我也知道,但如果一个接一个地叫他们,他们似乎会做多余的工作C++ 什么';这是提取最小值、最大值和最大值的最有效方法;向量中值,c++,algorithm,median,C++,Algorithm,Median,给定一个向量向量{…}假设T是一种数值类型,提取其最小值、最大值和中值的最佳方法是什么?我也知道,但如果一个接一个地叫他们,他们似乎会做多余的工作 到目前为止,我想到的最好的主意就是一个接一个地调用std::nth_元素3次。但这仍然需要3个比较,对吗?有没有办法重用以前迭代中完成的部分排序?使用std::nth_元素对产生中位数的部分进行划分,然后在左半部分使用std::min_元素,在右半部分使用std::max_元素 如果您需要更快的速度,那么根据std::nth_元素滚动您自己的版本。另
到目前为止,我想到的最好的主意就是一个接一个地调用std::nth_元素3次。但这仍然需要3个比较,对吗?有没有办法重用以前迭代中完成的部分排序?使用
std::nth_元素
对产生中位数的部分进行划分,然后在左半部分使用std::min_元素
,在右半部分使用std::max_元素
如果您需要更快的速度,那么根据
std::nth_元素
滚动您自己的版本。另一个选项是为std::nth_元素
指定自定义比较,它捕获最小值和最大值。它可能会进行更多的比较和分支,因此在某些特定硬件上可能会更慢,可能取决于缓存的数据量等,因此,如果您有理由关心,请一如既往地进行基准测试,但对于非空的向量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;
});
int min=a[0],max=a[0];
std::n_元素(a.begin(),a.begin()+n,a.end(),
[&](内部左侧,内部右侧){
最小=标准::最小(最小,标准::最小(左侧,右侧));
最大值=标准::最大值(最大值,标准::最大值(左侧,右侧));
返回左侧<右侧;
});
不管它值多少钱,在我的(~10yo i5-660)HTPC上,使用GCC 7.4,100万随机int
s介于0和1000之间,n\u元素
使用最小值/最大值比较比不使用该元素花费的时间长约36%。最有效的方法是手动循环并同时计算所有元素。@奇怪的是,如何通过迭代元素来获得中值?std::partial\u sort()
?std::n\u元素
,然后左半部分是std::min_元素
,右半部分是std::max_元素
。@DanielLangr,您假设std::nth_元素
将至少检查所有元素一次。这是合理的,但技术上不能保证。@BiagioFesta:有趣的一点;没有语言规范的保证,但我认为它在逻辑上不可能以其他方式工作…?当然,理论计算机科学中有一些关于算法复杂性的证明。但是,C++标准甚至没有指定使用哪一个算法来实现<代码> STD::NthyEngult。如果我必须写生产代码,我会自己实现完整的算法。@BiagioFesta:这段代码的正确性与其时间复杂度不同。我想说,不言而喻的是,n_元素
如果不对每个元素至少调用一次所提供的比较函子,就不可能按照要求重新排列输入数据,但您是对的,当它多次调用它时,可能会对性能产生负面影响/无法预测实现不透明时的严重程度;但在最坏的情况下,这将使比较翻一番,因此没有大的变化。你可以测量,这会让你感觉到它是否值得担心