Namespaces
Variants

std::nth_element

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)

Operaciones de ordenación y relacionadas
Operaciones de partición
(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 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 nth se cambia al elemento que ocurriría en esa posición si [first, last) estuviera ordenado.
  • Para cada iterador i en [first, nth) y cada iterador j en [nth, last), se cumple la siguiente condición:
1,2) bool(*j < *i)(hasta C++20)std::less{}(*j, *i)(desde C++20) es false.
3,4) bool(comp(*j, *i)) es false.


1) Los elementos se ordenan hipotéticamente sorted con respecto a operator<(hasta C++20)std::less{}(desde C++20).
3) Los elementos se ordenan hipotéticamente con respecto a comp.
2,4) Igual que (1,3), pero ejecutado de acuerdo con policy.
Estas sobrecargas participan en la resolución de sobrecarga solo si el valor de la siguiente expresión es true:

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>

(hasta C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>

(desde C++20)

Si se cumple alguna de las siguientes condiciones, el comportamiento es indefinido:

(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:

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

Si bien la firma no necesita tener const&, la función no debe modificar los objetos que se le pasan y debe poder aceptar todos los valores de tipo (posiblemente const) Type1 y Type2 independientemente de la categoría de valor (por lo tanto, no se permite Type1&, ni Type1 a menos que para Type1 un movimiento sea equivalente a una copia(desde C++11)).
Los tipos Type1 y Type2 deben ser tales que un objeto de tipo RandomIt pueda ser desreferenciado y luego convertido implícitamente a ambos. ​

Requisitos de tipo
-
RandomIt debe cumplir los requisitos de LegacyRandomAccessIterator.
-
Compare debe cumplir los requisitos de Compare.

Complejidad

Dado N como last - first:

1) O(N) comparaciones usando operator<(hasta C++20)std::less{}(desde C++20) en promedio.
2) O(N) comparaciones usando operator<(hasta C++20)std::less{}(desde C++20), y O(N·log(N)) intercambios.
3) O(N) aplicaciones del comparador comp en promedio.
4) O(N) aplicaciones del comparador 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 ExecutionPolicy es una de las políticas estándar, se llama a std::terminate. Para cualquier otro ExecutionPolicy, 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 nth
no 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)
devuelve el elemento más pequeño en un rango
(plantilla de función & objeto función de algoritmo)
copia y ordena parcialmente un rango de elementos
(plantilla de función & objeto función de algoritmo)
ordena un rango de elementos mientras conserva el orden relativo entre elementos equivalentes
(plantilla de función & objeto función de algoritmo)
ordena un rango de elementos
(plantilla de función & objeto función de algoritmo)
encuentra el enésimo elemento si el rango estuviera ordenado
(objeto función de algoritmo)