std:: equal_range
|
Definido en el encabezado
<algorithm>
|
||
| (1) | ||
|
template
<
class
ForwardIt,
class
T
>
std::
pair
<
ForwardIt, ForwardIt
>
|
(constexpr desde C++20)
(hasta C++26) |
|
|
template
<
class
ForwardIt,
class
T
=
typename
std::
iterator_traits
<
ForwardIt
>
::
value_type
>
|
(desde C++26) | |
| (2) | ||
|
template
<
class
ForwardIt,
class
T,
class
Compare
>
std::
pair
<
ForwardIt, ForwardIt
>
|
(constexpr desde C++20)
(hasta C++26) |
|
|
template
<
class
ForwardIt,
class
T
=
typename
std::
iterator_traits
<
ForwardIt
>
::
value_type
,
|
(desde C++26) | |
Devuelve un rango que contiene todos los elementos equivalentes a
value
en el rango particionado
[
first
,
last
)
.
|
Devuelve los resultados de std:: lower_bound ( first, last, value ) y std:: upper_bound ( first, last, value ) . Si se satisface alguna de las siguientes condiciones, el comportamiento es indefinido:
|
(hasta C++20) |
|
Equivalente a std :: equal_range ( first, last, value, std:: less { } ) . |
(desde C++20) |
-
Para cualquier elemento
elem
de
[first,last), bool ( comp ( elem, value ) ) no implica ! bool ( comp ( value, elem ) ) . -
Los elementos
elem
de
[first,last)no están particionados con respecto a las expresiones bool ( comp ( elem, value ) ) y ! bool ( comp ( value, elem ) ) .
Contenidos |
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: 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)
|
| 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
Un std::pair que contiene un par de iteradores, donde
-
firstes un iterador al primer elemento del rango[first,last)no ordenado antes de value (o last si no se encuentra tal elemento), y -
secondes un iterador al primer elemento del rango[first,last)ordenado después de value (o last si no se encuentra tal elemento).
Complejidad
Dado N como std:: distance ( first, last ) :
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::set
y
std::multiset
no son de acceso aleatorio, por lo que sus funciones miembro
std::set::equal_range
(resp.
std::multiset::equal_range
) deberían preferirse.
Notas
Aunque
std::equal_range
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
.
Además de los requisitos de
std::lower_bound
y
std::upper_bound
,
std::equal_range
también requiere que
operator
<
o
comp
sean asimétricos (es decir,
a
<
b
y
b
<
a
siempre tengan resultados diferentes).
Por lo tanto, los resultados intermedios de la búsqueda binaria pueden ser compartidos por
std::lower_bound
y
std::upper_bound
. Por ejemplo, el resultado de la llamada
std::lower_bound
puede usarse como argumento de
first
en la llamada
std::upper_bound
.
| 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
| equal_range (1) |
|---|
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type> constexpr std::pair<ForwardIt, ForwardIt> equal_range(ForwardIt first, ForwardIt last, const T& value) { return std::equal_range(first, last, value, std::less{}); } |
| equal_range (2) |
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type, class Compare> constexpr std::pair<ForwardIt, ForwardIt> equal_range(ForwardIt first, ForwardIt last, const T& value, Compare comp) { return std::make_pair(std::lower_bound(first, last, value, comp), std::upper_bound(first, last, value, comp)); } |
Ejemplo
#include <algorithm> #include <complex> #include <iostream> #include <vector> struct S { int number; char name; // nota: name es ignorado por este operador de comparación bool operator<(const S& s) const { return number < s.number; } }; struct Comp { bool operator()(const S& s, int i) const { return s.number < i; } bool operator()(int i, const S& s) const { return i < s.number; } }; int main() { // nota: no está ordenado, solo particionado respecto a S definido abajo const std::vector<S> vec{{1, 'A'}, {2, 'B'}, {2, 'C'}, {2, 'D'}, {4, 'G'}, {3, 'F'}}; const S value{2, '?'}; std::cout << "Comparar usando S::operator<(): "; const auto p = std::equal_range(vec.begin(), vec.end(), value); for (auto it = p.first; it != p.second; ++it) std::cout << it->name << ' '; std::cout << '\n'; std::cout << "Usando comparación heterogénea: "; const auto p2 = std::equal_range(vec.begin(), vec.end(), 2, Comp{}); for (auto it = p2.first; it != p2.second; ++it) std::cout << it->name << ' '; 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 p3 = std::equal_range(nums.cbegin(), nums.cend(), {2, 0}, cmpz); #else auto p3 = std::equal_range(nums.cbegin(), nums.cend(), CD{2, 0}, cmpz); #endif for (auto it = p3.first; it != p3.second; ++it) std::cout << *it << ' '; std::cout << '\n'; }
Salida:
Comparar usando S::operator<(): B C D Usando comparación heterogénea: B C D (2,2) (2, 1)
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
se requería que cumpliera con
Compare
y
T
se requería
que fuera LessThanComparable (se requería ordenamiento débil estricto) |
solo se requiere una partición;
se permiten comparaciones heterogéneas |
| LWG 384 | C++98 |
como máximo
2log
2
(N)+1
comparaciones
estaban permitidas, lo cual no es implementable [1] |
corregido a 2log 2 (N)+O(1) |
-
↑
Aplicar
equal_rangea un rango de un solo elemento requiere 2 comparaciones, pero como máximo se permite 1 comparación según el requisito de complejidad.
Véase también
|
devuelve un iterador al primer elemento
no menor
que el valor dado
(plantilla de función) |
|
|
devuelve un iterador al primer elemento
mayor
que cierto valor
(plantilla de función) |
|
|
determina si un elemento existe en un rango parcialmente ordenado
(plantilla de función) |
|
|
divide un rango de elementos en dos grupos
(plantilla de función) |
|
|
determina si dos conjuntos de elementos son iguales
(plantilla de función) |
|
|
devuelve el rango de elementos que coinciden con una clave específica
(función miembro pública de
std::set<Key,Compare,Allocator>
)
|
|
|
devuelve el rango de elementos que coinciden con una clave específica
(función miembro pública de
std::multiset<Key,Compare,Allocator>
)
|
|
|
(C++20)
|
devuelve el rango de elementos que coinciden con una clave específica
(objeto función de algoritmo) |