Espacios de nombres
Variantes
Acciones

std::adjacent_difference

De cppreference.com
< cpp‎ | algorithm
 
 
Biblioteca de algoritmos
Políticas de ejecución (C++17)
Operaciones de secuencia no modificantes
(C++11)(C++11)(C++11)
(C++17)
Operaciones de secuencia modificantes
Operaciones en almacenamiento no inicializado
Operaciones de partición
Operaciones de ordenación
(C++11)
Operaciones de búsqueda binaria
Operaciones de conjuntos (en rangos ordenados)
Operaciones de pila
(C++11)
Operaciones mínimo/máximo
(C++11)
(C++17)
Permutaciones
Operaciones numéricas
(C++11)
adjacent_difference
Bibliotecas C
 
Definido en el archivo de encabezado <numeric>
(1)
template< class InputIt, class OutputIt >

OutputIt adjacent_difference( InputIt first, InputIt last,

                              OutputIt d_first );
(hasta C++20)
template< class InputIt, class OutputIt >

constexpr OutputIt adjacent_difference( InputIt first, InputIt last,

                                        OutputIt d_first );
(desde C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 >

ForwardIt2 adjacent_difference( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last,

                                ForwardIt2 d_first );
(2) (desde C++17)
(3)
template< class InputIt, class OutputIt, class BinaryOperation >

OutputIt adjacent_difference( InputIt first, InputIt last,

                              OutputIt d_first, BinaryOperation op );
(hasta C++20)
template< class InputIt, class OutputIt, class BinaryOperation >

constexpr OutputIt adjacent_difference( InputIt first, InputIt last,

                                        OutputIt d_first, BinaryOperation op );
(desde C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryOperation >

ForwardIt2 adjacent_difference( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last,

                                ForwardIt2 d_first, BinaryOperation op );
(4) (desde C++17)

Calcula las diferencias entre el segundo y el primero de cada par de elementos adyacentes del rango [first, last) y las escribe en el rango que comienza en d_first + 1. Una copia sin modificar de *first se escribe en *d_first.

1,3) Primero, crea un acumulador acc cuyo tipo es el tipo de valor de InputIt, lo inicializa con *first y asigna el resultado a *d_first. Luego, para cada iterador i en [first + 1, last) en orden, crea un objeto val cuyo tipo es el tipo valor de InputIt, lo inicializa con *i, calcula val - acc (hasta C++20)val - std::move(acc) (desde C++20) (sobrecarga (1)) o op(val, acc) (hasta C++20)op(val, std::move(acc)) (desde C++20) (sobrecarga (3)), asigna el resultado a *(d_first + (i - first)), y mueve por asignación de val a acc.
first puede ser igual a d_first.
2,4) Ejecuta *d_first = *first;. Para cada d en [1, last - first - 1], asigna *(first + d) - *(first + d - 1) (sobrecarga (2)) o op(*(first + d), *(first + d - 1)) (sobrecarga (4)) to *(d_first + d). Esto se ejecuta de acuerdo con policy. Estas sobrecargas no participan en la resolución de sobrecarga a menos que 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) sea verdadera.
El comportamiento no está definido si los rangos de entrada y salida se superponen de alguna manera.


Operación equivalente:

*(d_first)   = *first;
*(d_first+1) = *(first+1) - *(first);
*(d_first+2) = *(first+2) - *(first+1);
*(d_first+3) = *(first+3) - *(first+2);
...

op no debe tener efectos secundarios.

(hasta C++11)

op no debe invalidar ningún iterador, incluidos los iteradores finales, ni modificar ningún elemento de los rangos involucrados.

(desde C++11)

Contenido

[editar] Parámetros

first, last - El rango de elementos.
d_first - El comienzo del rango de destino.
policy - La política de ejecución a usar. Véase política de ejecución para más detalles.
op - Función objeto de operación binaria que se aplicará.

La signatura de la función deberá ser equivalente a lo siguiente:

 Ret fun(const Type1 &a, const Type2 &b);

La signatura no necesita tener const &.
Los tipos Type1 y Type2 deben ser tales que un objeto de tipo iterator_traits<InputIt>::value_type puede convertirse implícitamente a ambos. El tipo Ret debe ser tal que un objeto de tipo OutputIt puede ser desreferenciado y asignado un valor de tipo Ret. ​

Requisitos de tipo
-
InputIt debe satisfacer los requisitos de InputIterator. El tipo valor de InputIt debe ser MoveAssignable y construible a partir del tipo de *first.
-
OutputIt debe satisfacer los requisitos de OutputIterator. Tanto acc (el valor acumulado) como el resultado de val - acc o op(val, acc) (hasta C++20)val - std::move(acc) o op(val, std::move(acc)) (desde C++20) deben ser escribibles en OutputIt.
-
ForwardIt1, ForwardIt2 debe satisfacer los requisitos de ForwardIterator. Los resultados de *first, *first - *first (para (2)) y op(*first, *first) (para (4)) deben ser escribibles en ForwardIt2.

[editar] Valor de retorno

Iterador al elemento más allá del último elemento escrito.

[editar] Notas

Si first == last, esta función no tiene efecto y simplemente devolverá d_first.

[editar] Complejidad

Exactamente (last - first) - 1 aplicaciones de la operación binaria.

[editar] Excepciones

Las sobrecargas con un parámetro de plantilla llamado ExecutionPolicy (política de ejecución) reportan errores tales que:

  • Si la ejecución de una función invocada como parte del algoritmo lanza una excepción y la política de ejecución es una de las tres políticas estándar, se llama a std::terminate. Para cualquier otra política de ejecución, el comportamiento está definido por la implementación.
  • Si el algoritmo falla al asignar memoria, se lanza std::bad_alloc.

[editar] Posible implementación

Primera versión
template<class InputIt, class OutputIt>
constexpr // desde C++20
OutputIt adjacent_difference(InputIt first, InputIt last, 
                             OutputIt d_first)
{
    if (first == last) return d_first;
 
    typedef typename std::iterator_traits<InputIt>::value_type value_t;
    value_t acc = *first;
    *d_first = acc;
    while (++first != last) {
        value_t val = *first;
        *++d_first = val - std::move(acc); // std::move desde C++20
        acc = std::move(val);
    }
    return ++d_first;
}
Segunda versión
template<class InputIt, class OutputIt, class BinaryOperation>
constexpr // desde C++20
OutputIt adjacent_difference(InputIt first, InputIt last, 
                             OutputIt d_first, BinaryOperation op)
{
    if (first == last) return d_first;
 
    typedef typename std::iterator_traits<InputIt>::value_type value_t;
    value_t acc = *first;
    *d_first = acc;
    while (++first != last) {
        value_t val = *first;
        *++d_first = op(val, std::move(acc)); // std::move desde C++20
        acc = std::move(val);
    }
    return ++d_first;
}

[editar] Ejemplo

#include <numeric>
#include <vector>
#include <array>
#include <iostream>
#include <functional>
#include <iterator>
 
auto imprimir = [](auto comentario, auto const& secuencia) {
    std::cout << comentario;
    for (const auto& n : secuencia)
        std::cout << n << ' ';
    std::cout << '\n';
};
 
int main()
{
    // Implementación por defecto: la diferencia entre dos elementos adyacentes
 
    std::vector v {4, 6, 9, 13, 18, 19, 19, 15, 10};
    imprimir("Inicialmente: v = ", v);
    std::adjacent_difference(v.begin(), v.end(), v.begin());
    imprimir("Modificada: v = ", v);
 
    // Fibonacci
 
    std::array<int, 10> a {1};
    adjacent_difference(begin(a), std::prev(end(a)), std::next(begin(a)), std::plus<> {});
    imprimir("Fibonacci: a = ", a);
}

Salida:

Inicialmente: v = 4 6 9 13 18 19 19 15 10 
Modificada: v = 4 2 3 4 5 1 0 -4 -5 
Fibonacci: a = 1 1 2 3 5 8 13 21 34 55

[editar] Véase también

Calcula la suma parcial de un rango de elementos
(plantilla de función) [editar]
Suma un rango de elementos
(plantilla de función) [editar]