了解 nth_element
Posted
技术标签:
【中文标题】了解 nth_element【英文标题】:Towards understanding nth_element 【发布时间】:2018-05-05 16:57:43 【问题描述】:我很难掌握应该如何使用std::nth_element
,因为我有点生疏了。
裁判说:
重新排列
[first,last)
范围内的元素,使第n 个位置的元素成为排序序列中该位置的元素。
我想获取向量子集的第 n 个元素,所以我想这样做:
std::nth_element (v.begin()+start-0, v.begin()+nTh-1, v.begin()+end);
意思是取向量v
的子集,从start
直到end
(不包括),然后假设这个子集已排序,定位nTh
元素。
似乎我的理解是错误的,因为这个玩具示例:
#include <iostream>
#include <algorithm>
#include <vector>
int main ()
std::vector<int> myvector;
// set some values:
for (int i=1; i<10; i++) myvector.push_back(i); // 1 2 3 4 5 6 7 8 9
std::random_shuffle (myvector.begin(), myvector.end());
std::nth_element (myvector.begin() + 1 - 0, myvector.begin()+5-1, myvector.begin() + 5);
std::cout << *(myvector.begin()+5-1) << std::endl;
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
打印 9 作为请求的元素,而我期待 5。请问我错过了什么?
【问题讨论】:
cplusplus.com 上的例子不是很简洁,使用Cppreference 根据我目前的经验,cppreference 通常是更好的参考。 @Rakete1111 和 WhiZTim,感谢您的提示! Baum mit Augen,它是学术性的,但对简单的事情没有那么友好和直接(但似乎我付出了这个代价)。 如果您甚至无法确定random_shuffle
之后的值 5
是否在您的 @987654333 涵盖的子范围内,您怎么可能“期望 5”(或任何其他特定值) @呼叫?
@gsamaras 我的回答是否遗漏了一些愚蠢的东西?我其实很困惑atm。
【参考方案1】:
试试:
std::nth_element (myvector.begin(), myvector.begin()+ 4, myvector.end());
而不是:
std::nth_element (myvector.begin() + 1,
myvector.begin() + 4,
myvector.begin() + 5);
您正在洗牌,然后只为一个子序列调用nth_element
。这样你就不能返回的元素应该是什么。如果你对整个序列都这样做,那么答案是 5。
【讨论】:
这不是答案。 @PeteBecker 我指出他使用的示例有一个错误。这解决了整个问题,因为nth-element
按他的预期工作。这怎么不是答案?
@PeteBecker 这很有趣,因为编辑后的版本实际上是我在编辑之前发布的原始版本。是的,我也很困惑。此外,这尽可能接近答案,因为问题本身存在问题。
你用刻薄的不回答替换了原来的答案,这就是我的评论。
@PeteBecker 因为我意识到他打算在子序列上调用nth_element
,而不是整个序列。目前的答案很奇怪。不知道为什么要回滚...不需要不必要的代码。它没有任何意义。【参考方案2】:
我想取向量子集的第 n 个元素,所以我想 做这样的事情:
std::nth_element (v.begin()+start-0, v.begin()+nTh-1, v.begin()+end);
表示从一开始就取向量 v 的子集,直到 结束(独占),然后想象这个子集是排序的, 定位第 n 个元素。
是的,这是真的。 但这样做时,位置 v[0] 到 v[start-1] 和 v[end] 到 v[v.size() - 1] 中的任何元素都不会成为 nth_element 重新排列的一部分,它们将停留在他们是。您作为 nth_element() 的一部分的 start 和 end 已将这些元素排除在重新排列之外。
我想你想要
std::nth_element (myvector.begin(), myvector.begin()+ 4, myvector.end());
考虑整个向量(nth_element 的第一个和第三个参数)。
这意味着无论 random_shuffle 在哪里洗牌
std::random_shuffle (myvector.begin(), myvector.end());
因为 nth_element 正在考虑整个向量,所以 nth_element 的第二个参数,如果已排序,myvector 中的第 5 个项目应该是 5。注意,由于 nth_element 的工作方式,前面的项目将小于 5(并且在任何order) 并且下一个项目将超过 5 个(并且以任何顺序)。
【讨论】:
以上是关于了解 nth_element的主要内容,如果未能解决你的问题,请参考以下文章