web-dev-qa-db-fra.com

Fonction <algorithme> pour trouver le dernier élément inférieur ou égal à, comme lower_bound

Existe-t-il une fonction qui utilise la recherche binaire, comme lower_bound mais qui retourne l'élément dernierinférieur ou égal à selon un prédicat donné?

lower_bound est défini comme:

Recherche la position de l'élément premier dans une plage ordonnée qui a une valeur supérieure ou équivalente à une valeur spécifiée, où le critère de classement peut être spécifié par un prédicat binaire.

et upper_bound:

Recherche la position de l'élément premier dans une plage ordonnée dont la valeur est supérieure à une valeur spécifiée, où le critère de classement peut être spécifié par un prédicat binaire.

Plus précisément, j'ai un conteneur d'événements ordonnés dans le temps et pour un temps donné, je veux trouver le dernier élément qui a précédé ou à ce moment-là. Puis-je y parvenir avec une combinaison de limite supérieure/inférieure, d'itérateurs inverses et en utilisant std::greater ou std::greater_equal?

EDIT: Un Tweak était nécessaire à la suggestion de user763305 pour faire face si vous demandez un point avant le début du tableau:

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

Dans un conteneur trié, le dernier élément inférieur ou équivalent à x est l'élément précédant le premier élément supérieur à x.

Ainsi, vous pouvez appeler std::upper_bound, et décrémenter l'itérateur retourné une fois. (Avant de décrémenter, vous devez bien sûr vérifier qu'il ne s'agit pas de l'itérateur de début; s'il l'est, alors il n'y a aucun élément inférieur ou équivalent à x.)

40
Johan Råde

Voici une fonction wrapper autour de upper_bound qui renvoie le plus grand nombre dans un conteneur ou un tableau qui est inférieur ou égal à une valeur donnée:

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

Pour une meilleure explication de ce que cela fait et comment utiliser cette fonction, consultez:

C++ STL - Recherche le dernier nombre inférieur ou égal à un élément donné dans un tableau ou un conteneur

7
user712850

J'ai testé votre solution d'itérateur inversé, elle est correcte.

Étant donné que v est trié par '<'

Trouver le dernier élément inférieur à 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;

Trouver le dernier élément inférieur à x égal:

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;

C'est mieux que iter -= 1 version

5
jean