Namespaces
Variants

std::ranges::lower_bound

De fr.cppreference.net
 
 
Bibliothèque d'algorithmes
Algorithmes contraints et algorithmes sur intervalles (C++20)
Algorithmes contraints, p.ex. ranges::copy, ranges::sort, ...
Opérations de séquence non modificatrices    
Opérations par lots
(C++17)
Opérations de recherche
Opérations de séquence modificatrices
Opérations de copie
(C++11)
(C++11)
Opérations d'échange
Opérations de transformation
Opérations de génération
Opérations de suppression
Opérations de changement d'ordre
(jusqu'à C++17)(C++11)
(C++20)(C++20)
Opérations d'échantillonnage
(C++17)

Tri et opérations associées
Opérations de partitionnement
(C++11)    

Opérations de tri
Opérations de recherche binaire
(sur intervalles partitionnés)
Opérations d'ensemble (sur intervalles triés)
Opérations de fusion (sur intervalles triés)
Opérations sur les tas
Opérations minimum/maximum
(C++11)
(C++17)
Opérations de comparaison lexicographique
Opérations de permutation


 
Algorithmes contraints
Tous les noms de ce menu appartiennent à l'espace de noms std::ranges
Opérations de séquence non modificatrices
Opérations de séquence modificatrices
Opérations de partitionnement
Opérations de tri
Opérations de recherche binaire (sur intervalles triés)
       
       
Opérations d'ensemble (sur intervalles triés)
Opérations sur les tas
Opérations minimum/maximum
       
       
Opérations de permutation
Opérations de pliage
Opérations sur le stockage non initialisé
Types de retour
 
Défini dans l'en-tête <algorithm>
Signature d'appel
template< std::forward_iterator I, std::sentinel_for<I> S,
          class T, class Proj = std::identity,
          std::indirect_strict_weak_order
              <const T*, std::projected<I, Proj>> Comp = ranges::less >
constexpr I lower_bound( I first, S last, const T& value,
                         Comp comp = {}, Proj proj = {} );
(1) (depuis C++20)
(jusqu'à C++26)
template< std::forward_iterator I, std::sentinel_for<I> S,
          class Proj = std::identity,
          class T = std::projected_value_t<I, Proj>,
          std::indirect_strict_weak_order
              <const T*, std::projected<I, Proj>> Comp = ranges::less >
constexpr I lower_bound( I first, S last, const T& value,
                         Comp comp = {}, Proj proj = {} );
(depuis C++26)
template< ranges::forward_range R,
          class T, class Proj = std::identity,
          std::indirect_strict_weak_order
              <const T*, std::projected<ranges::iterator_t<R>,
                                        Proj>> Comp = ranges::less >
constexpr ranges::borrowed_iterator_t<R>
    lower_bound( R&& r, const T& value, Comp comp = {}, Proj proj = {} );
(2) (depuis C++20)
(jusqu'à C++26)
template< ranges::forward_range R,
          class Proj = std::identity,
          class T = std::projected_value_t<ranges::iterator_t<R>, Proj>
          std::indirect_strict_weak_order
              <const T*, std::projected<ranges::iterator_t<R>,
                                        Proj>> Comp = ranges::less >
constexpr ranges::borrowed_iterator_t<R>
    lower_bound( R&& r, const T& value, Comp comp = {}, Proj proj = {} );
(depuis C++26)
1) Renvoie un itérateur pointant vers le premier élément de l'intervalle [firstlast) qui est non inférieur à (c'est-à-dire supérieur ou égal à) value, ou last si aucun élément de ce type n'est trouvé. L'intervalle [firstlast) doit être partitionné par rapport à l'expression std::invoke(comp, std::invoke(proj, element), value), c'est-à-dire que tous les éléments pour lesquels l'expression est true doivent précéder tous les éléments pour lesquels l'expression est false. Un intervalle entièrement trié satisfait ce critère.
2) Identique à (1), mais utilise r comme intervalle source, comme si en utilisant ranges::begin(r) comme first et ranges::end(r) comme last.

Les entités de type fonction décrites sur cette page sont objets fonction d'algorithmes (informellement appelés niebloids), c'est-à-dire :

Paramètres

first, last - la paire itérateur-sentinelle définissant la plage partiellement ordonnée des éléments à examiner
r - la plage partiellement ordonnée à examiner
value - valeur à comparer aux éléments projetés
comp - prédicat de comparaison à appliquer aux éléments projetés
proj - projection à appliquer aux éléments

Valeur de retour

Itérateur pointant vers le premier élément qui est non inférieur à value , ou last si aucun tel élément n'est trouvé.

Complexité

Le nombre de comparaisons et d'applications de la projection effectuées est logarithmique par rapport à la distance entre first et last (au plus log 2 (last - first) + O(1) comparaisons et applications de la projection). Cependant, pour un itérateur qui ne modélise pas random_access_iterator , le nombre d'incrémentations d'itérateur est linéaire.

Notes

Sur une plage entièrement triée (ou plus généralement, partiellement ordonnée par rapport à value ) après projection, std::ranges::lower_bound implémente l'algorithme de recherche binaire. Par conséquent, std::ranges::binary_search peut être implémentée en l'utilisant.

Macro de test de fonctionnalité Valeur Std Fonctionnalité
__cpp_lib_algorithm_default_value_type 202403 (C++26) Initialisation par liste pour les algorithmes ( 1,2 )

Implémentation possible

struct lower_bound_fn
{
    template<std::forward_iterator I, std::sentinel_for<I> S, class Proj = std::identity,
             class T = std::projected_value_t<I, Proj>,
             std::indirect_strict_weak_order
                 <const T*, std::projected<I, Proj>> Comp = ranges::less>
    constexpr I operator()(I first, S last, const T& value,
                           Comp comp = {}, Proj proj = {}) const
    {
        I it;
        std::iter_difference_t<I> count, step;
        count = std::ranges::distance(first, last);
        while (count > 0)
        {
            it = first;
            step = count / 2;
            ranges::advance(it, step, last);
            if (comp(std::invoke(proj, *it), value))
            {
                first = ++it;
                count -= step + 1;
            }
            else
                count = step;
        }
        return first;
    }
    template<ranges::forward_range R, class Proj = std::identity,
             class T = std::projected_value_t<ranges::iterator_t<R>, Proj>,
             std::indirect_strict_weak_order
                 <const T*, std::projected<ranges::iterator_t<R>,
                                           Proj>> Comp = ranges::less>
    constexpr ranges::borrowed_iterator_t<R>
        operator()(R&& r, const T& value, Comp comp = {}, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), value,
                       std::ref(comp), std::ref(proj));
    }
};
inline constexpr lower_bound_fn lower_bound;

Exemple

#include <algorithm>
#include <cassert>
#include <complex>
#include <iostream>
#include <iterator>
#include <vector>
namespace ranges = std::ranges;
template<std::forward_iterator I, std::sentinel_for<I> S, class T,
         class Proj = std::identity,
         std::indirect_strict_weak_order
             <const T*, std::projected<I, Proj>> Comp = ranges::less>
constexpr I binary_find(I first, S last, const T& value, Comp comp = {}, Proj proj = {})
{
    first = ranges::lower_bound(first, last, value, comp, proj);
    return first != last && !comp(value, proj(*first)) ? first : last;
}
int main()
{
    std::vector data{1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5};
    //                                 ^^^^^^^^^^
    auto lower = ranges::lower_bound(data, 4);
    auto upper = ranges::upper_bound(data, 4);
    std::cout << "found a range [" << ranges::distance(data.cbegin(), lower)
              << ", " << ranges::distance(data.cbegin(), upper) << ") = { ";
    ranges::copy(lower, upper, std::ostream_iterator<int>(std::cout, " "));
    std::cout << "}\n";
    // recherche binaire classique, retournant une valeur uniquement si elle est présente
    data = {1, 2, 4, 8, 16};
    //               ^
    auto it = binary_find(data.cbegin(), data.cend(), 8); // '5' retournerait end()
    if (it != data.cend())
        std::cout << *it << " trouvé à l'index " << ranges::distance(data.cbegin(), it);
    using CD = std::complex<double>;
    std::vector<CD> nums{{1, 0}, {2, 2}, {2, 1}, {3, 0}};
    auto cmpz = [](CD x, CD y) { return x.real() < y.real(); };
    #ifdef __cpp_lib_algorithm_default_value_type
        auto it2 = ranges::lower_bound(nums, {2, 0}, cmpz);
    #else
        auto it2 = ranges::lower_bound(nums, CD{2, 0}, cmpz);
    #endif
    assert((*it2 == CD{2, 2}));
}

Sortie :

found a range [6, 10) = { 4 4 4 4 }
8 found at index 3

Voir aussi

trouve la plage d'éléments correspondant à la valeur donnée en utilisant la recherche binaire
(objet fonction d'algorithme)
divise une plage d'éléments en deux groupes
(objet fonction d'algorithme)
localise le point de partition d'une plage partitionnée
(objet fonction d'algorithme)
trouve le premier élément supérieur à la valeur donnée en utilisant la recherche binaire
(objet fonction d'algorithme)
trouve le premier élément non inférieur à la valeur donnée en utilisant la recherche binaire
(modèle de fonction)