web-dev-qa-db-ja.com

<algorithm> lower_boundのように、以下の最後のアイテムを見つけるための関数

lower_boundのようなバイナリ検索を使用する関数がありますが、それはlastアイテムless-than-or-equal-toを返します与えられた述語に従って?

lower_boundは次のように定義されています。

first要素の位置を、指定された値以上の値を持つ順序付き範囲で検索します。順序付け基準は、バイナリ述語によって指定できます。

およびupper_bound

(= /// =)first要素の位置を、指定された値よりも大きい値を持つ順序付けされた範囲で検索します。基準はバイナリ述語で指定できます。

具体的には、時間順に並べられたイベントのコンテナがあり、ある時点で、その前またはその時点で最後のアイテムを見つけたいと考えています。上限/下限、逆反復子のいくつかの組み合わせとstd::greaterまたはstd::greater_equalを使用してこれを実現できますか?

編集:配列の開始前にポイントを要求した場合に対処するためのuser763305の提案にはTweakが必要でした:

iterator it=upper_bound(begin(), end(), val, LessThanFunction());
if (it!=begin()) {
  it--; // not at end of array so rewind to previous item
} else {
  it=end(); // no items before this point, so return end()
}
return it;
40
the_mandrill

ソートされたコンテナでは、x以下の最後の要素は、xより大きい最初の要素の前の要素です。

したがって、std::upper_boundを呼び出して、返された反復子を1回デクリメントできます。 (デクリメントする前に、もちろんそれが開始イテレーターでないことを確認する必要があります。そうである場合、xに等しいかそれ以下の要素はありません。)

40
Johan Råde

次に、upper_boundを囲むラッパー関数を示します。このラッパー関数は、指定された値以下のコンテナーまたは配列の最大数を返します。

template <class ForwardIterator, class T>
  ForwardIterator largest_less_than_or_equal_to ( ForwardIterator first, 
                                                  ForwardIterator last,
                                                  const T& value)
{
  ForwardIterator upperb = upper_bound(first, last, value);

  // First element is >, so none are <=
  if(upperb == first)
    return NULL;

  // All elements are <=, so return the largest.
  if(upperb == last)
    return --upperb;

  return upperb - 1;
}

これが何をしているか、そしてこの関数をどのように使用するかについてのより良い説明については、以下をチェックしてください:

C++ STL —配列またはコンテナー内の特定の要素以下の最後の数値を検索

7
user712850

私はあなたの逆反復子ソリューションをテストしました、それは正しいです。

与えられたvは「<」でソートされます

Xより小さい最後の要素を見つける:

auto iter = std::upper_bound(v.rbegin(), v.rend(), x, std::greater<int>());
if(iter == v.rend())
    std::cout<<"no found";
else
    std::cout<<*iter;

等しいxより小さい最後の要素を見つける:

auto iter = std::lower_bound(v.rbegin(), v.rend(), x, std::greater<int>());
if(iter == v.rend())
    std::cout<<"no found";
else
    std::cout<<*iter;

これはiter -= 1バージョンより優れています

5
jean