所以我想说我有以下结构
struct BadQuestion
{
float a;
float b;
} BadArray[10];
现在我需要检查哪个数组[i]的第二个最小值为'float a'。因为我后来需要从具有最小'float a'的数组中提取'float b'。
我看过像this这样的例子,但似乎有点过分了。有没有更简单快捷的方法来实现这一目标?
更新1:
bool cmp(const BadQuestion& lhs, const BadQuestion& rhs)
{
return lhs.a < rhs.a;
}
auto mini = std::min_element(BadArray, BadArray + 10, cmp);
mini->a
这会给我一个最小的值,这是一个很好的步骤。但我需要second
最低值。
答案 0 :(得分:0)
直截了当的方法很简单:
// n is assumed to be at least 2
int i0 = array[0].a<array[1].a ? 0 : 1, i1 = 1 - i0;
for (int i=2; i<n; i++) {
if (array[i].a < array[i1].a) {
if (array[i].a < array[i0].a) {
i1 = i0; i0 = i;
} else {
i1 = i;
}
}
}
// i0 is index of smallest a value, i1 is index of second-smallest
并且我非常确定现代编译器会将其转换为合理优化的机器代码(但是使用floats
可能不是速度的好主意。)
答案 1 :(得分:0)
根据您是否关心订单,有两种解决方案。
如果您在此操作之后不关心任何元素的排序,则可以使用标准算法nth_element。它会重新排序您的元素:
template <typename Iter, typename Cmp>
typename std::iterator_traits<Iter>::value_type
nth_smallest_reorder(Iter begin, Iter end, int n, Cmp cmp) {
std::nth_element(begin, begin + n, end, cmp);
return *(begin + n);
}
如果你做关心订购,那么你可以做两件事之一。首先,您可以直接复制整个阵列:
template <typename Iter, typename Cmp>
typename std::iterator_traits<Iter>::value_type
nth_smallest_copy(Iter begin, Iter end, int n, Cmp cmp) {
std::vector<typename std::iterator_traits<Iter>::value_type> cpy(begin, end);
std::nth_element(cpy.begin(), cpy.begin() + n, cpy.end(), cmp);
return cpy[n];
}
或者,您可以保留最多n+1
的运行排序列表:
template <typename Iter, typename Cmp>
typename std::iterator_traits<Iter>::value_type
nth_smallest_no_copy(Iter begin, Iter end, int n, Cmp cmp) {
std::vector<typename std::iterator_traits<Iter>::value_type> n_best;
n_best.reserve(n + 2);
for (; begin != end; ++begin) {
if (n_best.empty() || cmp(*begin, n_best.back())) {
n_best.insert(
std::lower_bound(n_best.begin(), n_best.end(), *begin, cmp),
*begin);
if (n_best.size() > n + 1) n_best.resize(n + 1);
}
}
return n_best.back();
}