std::nth_element
| Definido en el encabezado <algorithm>
|
||
template< class RandomIt >
void nth_element( RandomIt first, RandomIt nth, RandomIt last );
|
(1) | (constexpr desde C++20) |
template< class ExecutionPolicy, class RandomIt >
void nth_element( ExecutionPolicy&& policy,
RandomIt first, RandomIt nth, RandomIt last );
|
(2) | (desde C++17) |
template< class RandomIt, class Compare >
void nth_element( RandomIt first, RandomIt nth, RandomIt last,
Compare comp );
|
(3) | (constexpr desde C++20) |
template< class ExecutionPolicy, class RandomIt, class Compare >
void nth_element( ExecutionPolicy&& policy,
RandomIt first, RandomIt nth, RandomIt last,
Compare comp );
|
(4) | (desde C++17) |
nth_elementreordena los elementos en [first, last) de modo que después del reordenamiento:
- El elemento apuntado por
nthse cambia al elemento que ocurriría en esa posición si[first,last)estuviera ordenado. - Para cada iterador
ien[first,nth)y cada iteradorjen[nth,last), se cumple la siguiente condición:
bool(*j < *i)(hasta C++20)std::less{}(*j, *i)(desde C++20) es false.bool(comp(*j, *i)) es false.
operator<(hasta C++20)std::less{}(desde C++20).comp.policy.true:
|
|
(hasta C++20) |
|
|
(desde C++20) |
Si se cumple alguna de las siguientes condiciones, el comportamiento es indefinido:
[first,nth)o[nth,last)no es un rango válido.
|
(hasta C++11) |
|
(desde C++11) |
Parámetros
| first, last | - | el par de iteradores que definen el rango de elementos para la ordenación parcial |
| nth | - | iterador de acceso aleatorio que define el punto de partición de ordenación |
| policy | - | la política de ejecución a usar |
| comp | - | objeto función de comparación (es decir, un objeto que satisface los requisitos de Compare) que devuelve true si el primer argumento es menor que (es decir, está ordenado antes) que el segundo. La firma de la función de comparación debe ser equivalente a la siguiente:
Si bien la firma no necesita tener |
| Requisitos de tipo | ||
-RandomIt debe cumplir los requisitos de LegacyRandomAccessIterator.
| ||
-Compare debe cumplir los requisitos de Compare.
| ||
Complejidad
Dado N como last - first:
operator<(hasta C++20)std::less{}(desde C++20) en promedio.operator<(hasta C++20)std::less{}(desde C++20), y O(N·log(N)) intercambios.comp en promedio.comp, y O(N·log(N)) intercambios.Excepciones
Las sobrecargas con un parámetro de plantilla llamado ExecutionPolicy reportan errores de la siguiente manera:
- Si la ejecución de una función invocada como parte del algoritmo lanza una excepción y
ExecutionPolicyes una de las políticas estándar, se llama a std::terminate. Para cualquier otroExecutionPolicy, el comportamiento está definido por la implementación. - Si el algoritmo falla al asignar memoria, se lanza std::bad_alloc.
Posible implementación
Véase también las implementaciones en libstdc++, libc++ y MSVC STL.
Notas
El algoritmo utilizado es típicamente Introselect aunque otros algoritmos de selección con complejidad promedio adecuada están permitidos.
Ejemplo
#include <algorithm>
#include <cassert>
#include <functional>
#include <iostream>
#include <numeric>
#include <vector>
void printVec(const std::vector<int>& vec)
{
std::cout << "v = {";
for (char sep[]{0, ' ', 0}; const int i : vec)
std::cout << sep << i, sep[0] = ',';
std::cout << "};\n";
}
int main()
{
std::vector<int> v{5, 10, 6, 4, 3, 2, 6, 7, 9, 3};
printVec(v);
auto m = v.begin() + v.size() / 2;
std::nth_element(v.begin(), m, v.end());
std::cout << "\nThe median is " << v[v.size() / 2] << '\n';
// The consequence of the inequality of elements before/after the Nth one:
assert(std::accumulate(v.begin(), m, 0) < std::accumulate(m, v.end(), 0));
printVec(v);
// Note: comp function changed
std::nth_element(v.begin(), v.begin() + 1, v.end(), std::greater{});
std::cout << "\nThe second largest element is " << v[1] << '\n';
std::cout << "The largest element is " << v[0] << '\n';
printVec(v);
}
Posible salida:
v = {5, 10, 6, 4, 3, 2, 6, 7, 9, 3};
The median is 6
v = {3, 2, 3, 4, 5, 6, 10, 7, 9, 6};
The second largest element is 9
The largest element is 10
v = {10, 9, 6, 7, 6, 3, 5, 4, 3, 2};
Informes de defectos
Los siguientes informes de defectos que cambian el comportamiento se aplicaron retroactivamente a estándares C++ publicados anteriormente.
| DR | Aplicado a | Comportamiento como se publicó | Comportamiento correcto |
|---|---|---|---|
| LWG 2150 | C++98 | después del reordenamiento, solo se requería que un elemento antes de nthno fuera mayor que un elemento después de nth
|
se corrigió el requisito |
| LWG 2163 | C++98 | la sobrecarga (1) usaba operator> para comparar los elementos |
cambiado a operator<
|
| P0896R4 | C++98 | [first, nth) y [nth, last)no se requería que fueran rangos válidos |
el comportamiento es indefinido si alguno de ellos es inválido |
Véase también
| devuelve el elemento más grande en un rango (plantilla de función & objeto función de algoritmo) | |
(C++20) |
|
| devuelve el elemento más pequeño en un rango (plantilla de función & objeto función de algoritmo) | |
(C++20) |
|
| copia y ordena parcialmente un rango de elementos (plantilla de función & objeto función de algoritmo) | |
(C++20) |
|
| ordena un rango de elementos mientras conserva el orden relativo entre elementos equivalentes (plantilla de función & objeto función de algoritmo) | |
(C++20) |
|
| ordena un rango de elementos (plantilla de función & objeto función de algoritmo) | |
(C++20) |
|
(C++20) |
encuentra el enésimo elemento si el rango estuviera ordenado (objeto función de algoritmo) |