Namespaces
Variants

std::upper_bound

De es.cppreference.net
 
 
Biblioteca de algoritmos
Algoritmos restringidos y algoritmos sobre rangos (C++20)
Algoritmos restringidos, p.ej. 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)

Ordenación y operaciones relacionadas
Operaciones de particionado
(C++11)    

Operaciones de ordenación
Operaciones de búsqueda binaria
(en rangos particionados)
Operaciones de conjunto (en rangos ordenados)
Operaciones de fusión (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


 
Definido en el encabezado <algorithm>
template< class ForwardIt, class T >
ForwardIt upper_bound( ForwardIt first, ForwardIt last,
                       const T& value );
(1) (hasta C++26)
(constexpr desde C++20)
template< class ForwardIt, class T = typename std::iterator_traits
                                         <ForwardIt>::value_type >
constexpr ForwardIt upper_bound( ForwardIt first, ForwardIt last,
                                 const T& value );
(desde C++26)
template< class ForwardIt, class T, class Compare >
ForwardIt upper_bound( ForwardIt first, ForwardIt last,
                       const T& value, Compare comp );
(2) (hasta C++26)
template< class ForwardIt, class T = typename std::iterator_traits
                                         <ForwardIt>::value_type,
          class Compare >
constexpr ForwardIt upper_bound( ForwardIt first, ForwardIt last,
                                 const T& value, Compare comp );
(desde C++26)

Busca el primer elemento en el rango particionado [first, last) que está ordenado después de value.

1) El orden está determinado por operator<:

Devuelve el primer iterador iter en [first, last) donde bool(value < *iter) es true, o last si no existe tal iter existe.

Si los elementos elem de [first, last) no están particionados con respecto a la expresión bool(value < elem), el comportamiento no está definido.

(hasta C++20)

Equivalente a std::upper_bound(first, last, value, std::less{}).

(desde C++20)
2) El orden está determinado por comp:
Devuelve el primer iterador iter en [first, last) donde bool(comp(value, *iter)) es true, o last si no existe tal iter existe.
Si los elementos elem de [first, last) no están particionados con respecto a la expresión bool(comp(value, elem)), el comportamiento no está definido.

Parámetros

first, last - el par de iteradores que define el rango particionado de elementos a examinar
value - valor contra el cual comparar los elementos
comp - predicado binario que retorna ​ true si el primer argumento está ordenado antes del segundo.

La firma de la función predicado debe ser equivalente a lo siguiente:

bool pred ( const Type1 & a, const Type2 & b ) ;

Aunque la firma no necesita tener const & , la función no debe modificar los objetos pasados y debe poder aceptar todos los valores de tipo (posiblemente const) Type1 y Type2 independientemente de la categoría de valor (por lo tanto, Type1 & no está permitido , ni tampoco Type1 a menos que para Type1 un movimiento sea equivalente a una copia (desde C++11) ).
El tipo Type1 debe ser tal que un objeto de tipo T pueda convertirse implícitamente a Type1 . El tipo Type2 debe ser tal que un objeto de tipo ForwardIt pueda ser desreferenciado y luego convertido implícitamente a Type2 . ​

Requisitos de tipo
-
ForwardIt debe cumplir con los requisitos de LegacyForwardIterator .
-
Compare debe cumplir con los requisitos de BinaryPredicate . No se requiere que satisfaga Compare .

Valor de retorno

Iterador al primer elemento del rango [ first , last ) ordenado después de value , o last si no se encuentra dicho elemento.

Complejidad

Dado N como std:: distance ( first, last ) :

1) Como máximo log 2 (N)+O(1) comparaciones con value usando operator < (until C++20) std:: less { } (since C++20) .
2) Como máximo log 2 (N)+O(1) aplicaciones del comparador comp .

Sin embargo, si ForwardIt no es un LegacyRandomAccessIterator , el número de incrementos del iterador es lineal en N . Cabe destacar que los iteradores de std::map , std::multimap , std::set , y std::multiset no son de acceso aleatorio, por lo que deberían preferirse sus funciones miembro upper_bound .

Implementación posible

Consulte también las implementaciones en libstdc++ y libc++ .

upper_bound (1)
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type>
ForwardIt upper_bound(ForwardIt first, ForwardIt last, const T& value)
{
    return std::upper_bound(first, last, value, std::less{});
}
upper_bound (2)
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type,
         class Compare>
ForwardIt upper_bound(ForwardIt first, ForwardIt last, const T& value, Compare comp)
{
    ForwardIt it;
    typename std::iterator_traits<ForwardIt>::difference_type count, step;
    count = std::distance(first, last);
    while (count > 0)
    {
        it = first; 
        step = count / 2;
        std::advance(it, step);
        if (!comp(value, *it))
        {
            first = ++it;
            count -= step + 1;
        } 
        else
            count = step;
    }
    return first;
}

Notas

Aunque std::upper_bound solo requiere que [ first , last ) esté particionado, este algoritmo se utiliza normalmente en el caso donde [ first , last ) está ordenado, de modo que la búsqueda binaria es válida para cualquier value .

Para cualquier iterador iter en [ first , last ) , std::upper_bound requiere que value < * iter y comp ( value, * iter ) estén bien formados, mientras que std::lower_bound requiere que * iter < value y comp ( * iter, value ) estén bien formados en su lugar.

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

Ejemplo

#include <algorithm>
#include <cassert>
#include <complex>
#include <iostream>
#include <vector>
struct PriceInfo { double price; };
int main()
{
    const std::vector<int> data{1, 2, 4, 5, 5, 6};
    for (int i = 0; i < 7; ++i)
    {
        // Buscar el primer elemento que sea mayor que i
        auto upper = std::upper_bound(data.begin(), data.end(), i);
        std::cout << i << " < ";
        upper != data.end()
            ? std::cout << *upper << " en el índice " << std::distance(data.begin(), upper)
            : std::cout << "no encontrado";
        std::cout << '\n';
    }
    std::vector<PriceInfo> prices{{100.0}, {101.5}, {102.5}, {102.5}, {107.3}};
    for (double to_find : {102.5, 110.2})
    {
        auto prc_info = std::upper_bound(prices.begin(), prices.end(), to_find,
            [](double value, const PriceInfo& info)
            {
                return value < info.price;
            });
        prc_info != prices.end()
            ? std::cout << prc_info->price << " en el índice " << prc_info - prices.begin()
            : std::cout << to_find << " no encontrado";
        std::cout << '\n';
    }
    using CD = std::complex<double>;
    std::vector<CD> nums{{1, 0}, {2, 2}, {2, 1}, {3, 0}, {3, 1}};
    auto cmpz = [](CD x, CD y) { return x.real() < y.real(); };
    #ifdef __cpp_lib_algorithm_default_value_type
        auto it = std::upper_bound(nums.cbegin(), nums.cend(), {2, 0}, cmpz);
    #else
        auto it = std::upper_bound(nums.cbegin(), nums.cend(), CD{2, 0}, cmpz);
    #endif
    assert((*it == CD{3, 0}));
}

Salida:

0 < 1 en el índice 0
1 < 2 en el índice 1
2 < 4 en el índice 2
3 < 4 en el índice 2
4 < 5 en el índice 3
5 < 6 en el índice 5
6 < no encontrado 
107.3 en el índice 4
110.2 no encontrado

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
LWG 270 C++98 Compare debía satisfacer Compare y T debía ser
LessThanComparable (se requería ordenamiento débil estricto)
solo se requiere una partición;
se permiten comparaciones heterogéneas
LWG 384 C++98 se permitían como máximo log 2 (N)+1 comparaciones corregido a log 2 (N)+O(1)
LWG 577 C++98 last no podía ser devuelto permitido
LWG 2150 C++98 si existe cualquier iterador iter en [ first , last ) tal que
bool ( comp ( value, * iter ) ) es true , std::upper_bound
podría devolver cualquier iterador en [ iter , last )
no se puede devolver ningún iterador después de
iter

Ver también

encuentra el rango de elementos que coinciden con el valor dado mediante búsqueda binaria
(plantilla de función & objeto función de algoritmo)
encuentra el primer elemento no menor que el valor dado mediante búsqueda binaria
(plantilla de función & objeto función de algoritmo)
divide un rango de elementos en dos grupos
(plantilla de función & objeto función de algoritmo)
localiza el punto de partición de un rango particionado
(plantilla de función & objeto función de algoritmo)
encuentra el primer elemento mayor que el valor dado mediante búsqueda binaria
(objeto función de algoritmo)
devuelve un iterador al primer elemento mayor que la clave dada
(función miembro pública de std::set<Key,Compare,Allocator>)
devuelve un iterador al primer elemento mayor que la clave dada
(función miembro pública de std::multiset<Key,Compare,Allocator>)