Namespaces
Variants

std::ranges::lower_bound

Desde es.cppreference.net
 
 
Biblioteca de algoritmos
Algoritmos restringidos y algoritmos sobre rangos (C++20)
Algoritmos restringidos, e.g. ranges::copy, ranges::sort, ...
Operaciones de secuencia no modificadoras    
Operaciones por lotes
(C++17)
Operaciones de búsqueda
Operaciones de secuencia modificadoras
Operaciones de copia
(C++11)
(C++11)
Operaciones de intercambio
Operaciones de transformación
Operaciones de generación
Operaciones de eliminación
Operaciones de cambio de orden
(hasta C++17)(C++11)
(C++20)(C++20)
Operaciones de muestreo
(C++17)

Ordenamiento y operaciones relacionadas
Operaciones de particionado
(C++11)    

Operaciones de ordenamiento
Operaciones de búsqueda binaria
(en rangos particionados)
Operaciones de conjunto (en rangos ordenados)
Operaciones de mezcla (en rangos ordenados)
Operaciones de montículo
Operaciones de mínimo/máximo
(C++11)
(C++17)
Operaciones de comparación lexicográfica
Operaciones de permutación


 
Algoritmos restringidos
Todos los nombres en este menú pertenecen al espacio de nombres std::ranges
Operaciones de secuencia no modificadoras
Operaciones de secuencia modificadoras
Operaciones de particionado
Operaciones de ordenamiento
Operaciones de búsqueda binaria (en rangos ordenados)
       
       
Operaciones de conjunto (en rangos ordenados)
Operaciones de montículo
Operaciones de mínimo/máximo
       
       
Operaciones de permutación
Operaciones de pliegue
Operaciones sobre almacenamiento no inicializado
Tipos de retorno
 
Definido en el encabezado <algorithm>
Firma de llamada
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) (desde C++20)
(hasta 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 = {} );
(desde 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) (desde C++20)
(hasta 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 = {} );
(desde C++26)
1) Devuelve un iterador apuntando al primer elemento en el rango [first, last) que es no menor que (es decir, mayor o igual a) value, o last si no se encuentra tal elemento. El rango [first, last) debe estar particionado con respecto a la expresión std::invoke(comp, std::invoke(proj, element), value), es decir, todos los elementos para los cuales la expresión es true deben preceder a todos los elementos para los cuales la expresión es false. Un rango completamente ordenado cumple este criterio.
2) Igual que (1), pero utiliza r como el rango fuente, como si se usara ranges::begin(r) como first y ranges::end(r) como last.

Las entidades similares a funciones descritas en esta página son objetos de función de algoritmo (conocidos informalmente como niebloids), es decir:

Parámetros

first, last - el par iterador-centinela que define el rango parcialmente ordenado de elementos a examinar
r - el rango parcialmente ordenado a examinar
value - valor contra el cual comparar los elementos proyectados
comp - predicado de comparación a aplicar a los elementos proyectados
proj - proyección a aplicar a los elementos

Valor de retorno

Iterador que apunta al primer elemento que no es menor que value , o last si no se encuentra dicho elemento.

Complejidad

El número de comparaciones y aplicaciones de la proyección realizadas es logarítmico en la distancia entre first y last (como máximo log 2 (last - first) + O(1) comparaciones y aplicaciones de la proyección). Sin embargo, para un iterador que no modela random_access_iterator , el número de incrementos del iterador es lineal.

Notas

En un rango que está completamente ordenado (o más generalmente, parcialmente ordenado con respecto a value ) después de la proyección, std::ranges::lower_bound implementa el algoritmo de búsqueda binaria. Por lo tanto, std::ranges::binary_search puede implementarse en términos de este.

Macro de prueba de características Valor Std Característica
__cpp_lib_algorithm_default_value_type 202403 (C++26) Inicialización por lista para algoritmos ( 1,2 )

Implementación posible

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;

Ejemplo

#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";
    // búsqueda binaria clásica, devolviendo un valor solo si está presente
    data = {1, 2, 4, 8, 16};
    //               ^
    auto it = binary_find(data.cbegin(), data.cend(), 8); // '5' devolvería end()
    if (it != data.cend())
        std::cout << *it << " encontrado en el índice " << 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}));
}

Salida:

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

Véase también

encuentra el rango de elementos que coinciden con el valor dado usando búsqueda binaria
(objeto función de algoritmo)
divide un rango de elementos en dos grupos
(objeto función de algoritmo)
localiza el punto de partición de un rango particionado
(objeto función de algoritmo)
encuentra el primer elemento mayor que el valor dado usando búsqueda binaria
(objeto función de algoritmo)
encuentra el primer elemento no menor que el valor dado usando búsqueda binaria
(plantilla de función)