了解 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的主要内容,如果未能解决你的问题,请参考以下文章

了解了解grpc

数据库 了解知识

深入了解ASP.NET运行内幕

了解GStreamer

深入了解Java的String

Vue UI 了解一下