Namespaces
Variants

std::is_permutation

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 ordenamiento y relacionadas
Operaciones de particionamiento
(C++11)    

Operaciones de ordenamiento
Operaciones de búsqueda binaria
(sobre rangos particionados)
Operaciones de conjuntos (sobre rangos ordenados)
Operaciones de fusión (sobre 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 ForwardIt1, class ForwardIt2 >
bool is_permutation( ForwardIt1 first1, ForwardIt1 last1,
                     ForwardIt2 first2 );
(1) (desde C++11)
(constexpr desde C++20)
template< class ForwardIt1, class ForwardIt2,
          class BinaryPredicate >
bool is_permutation( ForwardIt1 first1, ForwardIt1 last1,
                     ForwardIt2 first2, BinaryPredicate p );
(2) (desde C++11)
(constexpr desde C++20)
template< class ForwardIt1, class ForwardIt2 >
bool is_permutation( ForwardIt1 first1, ForwardIt1 last1,
                     ForwardIt2 first2, ForwardIt2 last2 );
(3) (desde C++14)
(constexpr desde C++20)
template< class ForwardIt1, class ForwardIt2,
          class BinaryPredicate >
bool is_permutation( ForwardIt1 first1, ForwardIt1 last1,
                     ForwardIt2 first2, ForwardIt2 last2,
                     BinaryPredicate p );
(4) (desde C++14)
(constexpr desde C++20)

Comprueba si [first1, last1) es una permutación de un rango que comienza en first2:

  • Para las sobrecargas (1,2), el segundo rango tiene std::distance(first1, last1) elementos.
  • Para las sobrecargas (3,4), el segundo rango es [first2, last2).
1,3) Los elementos se comparan usando operator==.
2,4) Los elementos se comparan usando el predicado binario dado p.

Si ForwardIt1 y ForwardIt2 tienen diferentes tipos de valor, el programa está mal formado.

Si la función de comparación no es una relación de equivalencia, el comportamiento no está definido.

Parámetros

first1, last1 - el par de iteradores que definen el primer rango de elementos a comparar
first2, last2 - el par de iteradores que definen el segundo rango de elementos a comparar
p - predicado binario que devuelve ​true si los elementos deben ser tratados como iguales.

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

bool pred(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, Type1 & no está permitido, ni tampoco 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 los objetos de tipos InputIt1 y InputIt2 puedan ser desreferenciados y luego convertidos implícitamente a Type1 y Type2 respectivamente. ​

Requisitos de tipo
-
ForwardIt1, ForwardIt2 debe cumplir los requisitos de LegacyForwardIterator.

Valor de retorno

true si el rango [first1, last1) es una permutación del rango [first2, last2), false en caso contrario.

Complejidad

Dado N como std::distance(first1, last1):

1) Exactamente N comparaciones usando operator== si los dos rangos son iguales, en caso contrario O(N2
)
comparaciones en el peor caso.
2) Exactamente N aplicaciones del predicado p si los dos rangos son iguales, en caso contrario O(N2
)
aplicaciones en el peor caso.
3,4) Si ForwardIt1 y ForwardIt2 son ambos LegacyRandomAccessIterator, y last1 - first1 != last2 - first2 es true, no se realizará ninguna comparación.
En caso contrario:
3) Exactamente N comparaciones usando operator== si los dos rangos son iguales, en caso contrario O(N2
)
comparaciones en el peor caso.
4) Exactamente N aplicaciones del predicado p si los dos rangos son iguales, en caso contrario O(N2
)
aplicaciones en el peor caso.

Posible implementación

template<class ForwardIt1, class ForwardIt2>
bool is_permutation(ForwardIt1 first, ForwardIt1 last,
                    ForwardIt2 d_first)
{
    // skip common prefix
    std::tie(first, d_first) = std::mismatch(first, last, d_first);
    
    // iterate over the rest, counting how many times each element
    // from [first, last) appears in [d_first, d_last)
    if (first != last)
    {
        ForwardIt2 d_last = std::next(d_first, std::distance(first, last));
        for (ForwardIt1 i = first; i != last; ++i)
        {
            if (i != std::find(first, i, *i))
                continue; // this *i has been checked
            
            auto m = std::count(d_first, d_last, *i);
            if (m == 0 || std::count(i, last, *i) != m)
                return false;
        }
    }
    return true;
}

Nota

La std::is_permutation se puede usar en pruebas, es decir, para verificar la corrección de algoritmos de reordenamiento (p. ej., ordenamiento, mezcla, particionamiento). Si x es un rango original y y es un rango permutado entonces std::is_permutation(x, y) == true significa que y consiste en "los mismos" elementos, quizás en otras posiciones.

Ejemplo

#include <algorithm>
#include <iostream>

template<typename Os, typename V>
Os& operator<<(Os& os, const V& v)
{
    os << "{ ";
    for (const auto& e : v)
        os << e << ' ';
    return os << '}';
}

int main()
{
    static constexpr auto v1 = {1, 2, 3, 4, 5};
    static constexpr auto v2 = {3, 5, 4, 1, 2};
    static constexpr auto v3 = {3, 5, 4, 1, 1};
    
    std::cout << v2 << " is a permutation of " << v1 << ": " << std::boolalpha
              << std::is_permutation(v1.begin(), v1.end(), v2.begin()) << '\n'
              << v3 << " is a permutation of " << v1 << ": "
              << std::is_permutation(v1.begin(), v1.end(), v3.begin()) << '\n';
}

Salida:

{ 3 5 4 1 2 } is a permutation of { 1 2 3 4 5 }: true
{ 3 5 4 1 1 } is a permutation of { 1 2 3 4 5 }: false

Véase también

genera la siguiente permutación lexicográfica mayor de un rango de elementos
(plantilla de función & objeto función de algoritmo)
genera la siguiente permutación lexicográfica menor de un rango de elementos
(plantilla de función & objeto función de algoritmo)
especifica que una relación impone una relación de equivalencia
(concepto)
determina si una secuencia es una permutación de otra secuencia
(objeto función de algoritmo)