簡體   English   中英

std :: max_element用於第二大元素?

[英]std::max_element for second largest element?

STL提供std::max_element來查找可迭代的最大元素,例如:

std::vector<float>::const_iterator max = 
  std::max_element(obj.pt()->begin(), obj.pt()->end());
return std::distance(obj.pt()->begin(), max);

還有第n個最大元素可以得到迭代器的東西嗎?

(請注意, max_element返回一個迭代器,這實際上很重要:我不是在尋找值本身,而是在迭代器中尋找第n個最大元素的位置。)

如果您對第二大元素特別感興趣,則可以對數組進行簡單掃描,其中大多數元素需要進行一次比較:

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循環並不復雜。

正如Dyp在評論中提到的那樣,如果您可以更改vector中元素的順序,則可以如下使用std::nth_element 最重要的是,如果再次在vector使用find ,則會從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)

這是在線性時間內實現的簡單算法。 天真的方法是比較前兩個值,然后選擇它們作為最大值和第二個最大值。 然后,您需要遍歷其他元素,將每個新元素與兩個元素進行比較,並調整當前的最大值和第二最大值。 對於大多數用例來說,這可能綽綽有余。 如果你真的關心性能(如在你多多關照 ),你需要考慮你想比較,以盡量減少比較的次數什么樣的價值觀。

還要注意, float (通常是float )具有怪癖...如果您的輸入包含NaN或無限值,則可能會得到有趣的值。

我花了一段時間才找到解決方案,因為我使用了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

通過傳遞lambda函數可以將max_element()方法用於獲取第二大元素,該函數會將元素與先前找到的最大元素進行比較,如果它等於最大元素,則將直接跳過該元素。

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));
                                 });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM