我有一个结构向量,我为此重载了所有比较运算符。我不知道编译时结构的大小。
在向量中检索n个最佳元素(其中"最佳"可以是最小值还是最大值)的禁区方法是什么?我知道max_element和min_element但它们只返回一个元素。我宁愿不循环n次,检索最佳元素,删除它然后获取下一个元素。这种方法似乎太慢了。
感谢。
答案 0 :(得分:4)
您可以使用std::nth_element
,将最小的n
元素移动到范围中的第一个n
位置(注意这些n
元素的相对排序是未定义)。
std::vector<T> objects;
std::nth_element( objects.begin(), objects.begin() + n, objects.end() );
// Now the range [objects.begin(), objects.begin() + n) contains the lowest n elements
// Obviously n must be <= objects.size()
当你编写时,你不知道编译时结构的大小,我假设你有一个多态对象的集合,你有一个指针向量而不是元素。没什么大不了的,你仍然可以将std::nth_element
与lambda一起使用。
std::vector<T*> objects;
std::nth_element( objects.begin(),
objects.begin() + n,
objects.end(),
[](const T * lhs, const T * rhs)
{
return (*lhs) < (*rhs); // Or (*lhs) > (*rhs) for the greatest n elements
});
答案 1 :(得分:1)
对它进行排序,然后取n个元素。
struct Foo { };
std::vector<Foo> v = { Foo(), Foo(), Foo() };
std::sort(v.begin(), v.end());
std::vector<Foo> v_best(v.begin(), v.begin() + n); //where n is your best count
答案 2 :(得分:1)
另一种方法,而不是蛮力排序和第一步:设置一个大小为n
的临时容器,并使用原始向量的第一个n
元素对其进行初始化(例如,大小为N
。对该临时矢量进行排序。
接下来遍历原始向量并插入元素(使用std::lower_bound
),只要它们大于已排序容器的当前最小值(同时抛出当前最小值)。这应首先取O(n log n + N)
而不是O(N log N)
渐近,但更重要的是,常数前因子也可能小得多。
答案 3 :(得分:0)
如果要检索n
个最小元素,请按升序排序vector
。
如果要检索n
个最大元素,请按降序排序vector
。
然后,
获取两个迭代器。
start = v.begin();
end = start + n;
从start
到end
进行迭代,但不包括end
。
答案 4 :(得分:0)
此处的其他答案有效,但您也可以使用copy_if。
std::vector<int> vec{ 1, 5, 7, 9, 3, 6, 8, 4, 2 };
std::vector<int> odd;
std::copy_if(vec.begin(), vec.end(), std::back_inserter(odd), [](int a){ return a % 2 == 1; });
std::vector<int> low;
std::copy_if(vec.begin(), vec.end(), std::back_inserter(low), [](int a){ return a <= 3; });
std::vector<int> high;
std::copy_if(vec.begin(), vec.end(), std::back_inserter(high), [](int a){ return a >= 7; });
如果您需要删除匹配的数据,还有remove_copy_if。
答案 5 :(得分:0)
我建议你一个解决方案既不修改也不复制矢量:
所以我假设原始矢量非常大,你仍然需要原始顺序的数据用于其他目的
template <typename T>
set<T> best_n2(vector<T>& v, size_t n)
{
set<int> u; // the result is a sorted set
int i = 0;
for (auto x : v) { // fill the N first elements
if (i++ < n) {
u.insert(x);
}
else if (x > *u.begin()) { // then get rid of the smallest if necessray
u.erase(*u.begin());
u.insert(x);
}
}
return u;
}
如果你可以修改原始矢量,我选择szulack的解决方案。我没有提出建议,因为他的打字速度比我快得多; - )