std :: max_element是第二大元素?

时间:2015-05-27 16:47:59

标签: c++ stl

STL提供jQuery("div.myclass script").replaceWith(""); 来查找可迭代中的最大元素,例如像这样:

std::max_element

是否还有东西可以获得第n个最大元素的迭代器?

(注意std::vector<float>::const_iterator max = std::max_element(obj.pt()->begin(), obj.pt()->end()); return std::distance(obj.pt()->begin(), max); 返回一个迭代器,这实际上很重要:而不是对于值本身,我正在寻找迭代中第n个最大元素的位置。)

5 个答案:

答案 0 :(得分:2)

如果您对第二大元素特别感兴趣,可以对数组进行简单扫描,其中大多数元素需要进行单一比较:

float second_largest_element(std::vector<float> vec) {
  float m2, m1;
  /* Check to make sure that vec has at least 2 elements!! */
  std::tie(m2, m1) = std::minmax(vec[0], vec[1]);
  for (auto it = vec.begin() + 2, limit = vec.end();
       it != limit;
       ++it)
    if (*it > m2) std::tie(m2, m1) = std::minmax(*it, m1);
  return m2;
}

获取第二大元素的索引(或迭代器)非常相似,尽管std::minmax不太有用。这是一个非常草率的例子:

template<typename T>
typename T::iterator second_largest(T& container) {
  using iterator = typename T::iterator;
  iterator limit = container.end();
  iterator it = container.begin();
  if (it != limit) {
    iterator first = it++;
    if (it != limit) {
      iterator second = it++;
      if (*first < *second) std::swap(first, second);
      for (; it != limit; ++it) {
        if (*second < *it) {
          if (*first < *it) { second = first; first = it; }
          else              { second = it; }
        }
      }
      return second;
    }
    return first;
  }
  return it;
}

您也可以考虑使用std::accumulate来扫描数组,尽管显式for循环并不复杂。

答案 1 :(得分:1)

正如Dyp在评论中提到的,如果您可以改变vector中元素的顺序,可以使用std::nth_element,如下所示。如果您再次使用find而不是vector,则会获得vector中第n个元素的原始位置。由于nth_element修改了位置,因此您必须先保留其本地副本,然后才能对向量进行nth_element操作。

第二大元素:

std::vector<float> orig_vec=obj.pt;

std::nth_element(obj.pt().begin(), obj.pt().begin()+1, 
                  obj.pt().end(), std::greater<float>());
float 2nd= *(obj.pt().begin()+1);
auto it=std::find(orig_vec.begin(), orig_vec.end(), 2nd);

第n个最大元素:

  std::nth_element(obj.pt().begin(), obj.pt().begin()+n-1,
    obj.pt().end(), std::greater<float>());
  float nth= *(obj.pt().begin()+n-1);

 auto it=std::find(orig_vec.begin(), orig_vec.end(), nth)

答案 2 :(得分:0)

这是一个在线性时间内实现的简单算法。天真的方法是比较前两个值,并选择它们作为最大值和第二大值。然后,您需要迭代其他元素,将每个新元素与两个元素进行比较,并调整当前的最大值和第二大值。对于大多数用例来说,这可能是绰绰有余的。如果你真的关心表现(就像你在乎很多),你需要考虑你想要比较的值,以尽量减少比较次数。

另请注意float(一般浮点)有怪癖......如果您的输入包含NaN或无限值,您可能会得到有趣的值。

答案 3 :(得分:0)

花了我一段时间才找到解决方案,因为我使用了const vector(因此我不能使用nth_element),而复制只会浪费掉(特别是当vector拥有更大的结构时)。所以我来了:

// Find 1st max
auto max1 = max_element(vec.begin(), vec.end());
if (max1 != vec.end())
    // Use max1

// Find 2nd max. Split the vector into 2 parts, find max and merge results
auto max2Beg = max_element(vec.begin(), max1);
auto max2End = max_element(max1 + 1, vec.end());
auto max2 = max2Beg == max1 ? max2End :
            max2End == vec.end() ? max2Beg : max(max2Beg, max2End);
if (max2 != max1 && max2 != vec.end())
    // Use max2

答案 4 :(得分:0)

max_element()方法可通过传递lambda函数来获取第二大元素,该函数将元素与先前找到的最大元素进行比较,如果它等于最大元素,则将跳过该元素。

auto largest = max_element(vec.begin(), vec.end());
auto secondLargest = max_element(vec.begin(), vec.end(),
                                 [&largest](unsigned long &a, unsigned long &b) {
                                     return ((b != (*largest)) && (a < b));
                                 });