嵌入式C++低功耗设计

Los algoritmos de la STL en C++ se clasifican en varias categorías según su efecto sobre los datos. A continuación se presentan ejemplos prácticos con implementaciones modificadas para reducir el consumo energético en sistemas embebidos, aunque los principios algorítmicos son los mismos.

1. Algoritmos de solo lectura

No alteran el contenedor original.

1.1 find y find_if

localizan un elemento o el primero que cumple una condición.

std::list<int> datos = {8, 2, 6, 4, 10};
auto pos = std::find(datos.begin(), datos.end(), 6);
if (pos != datos.end()) {
    // valor 6 encontrado
}

auto posPar = std::find_if(datos.begin(), datos.end(),
                           [](int x) { return x % 2 == 0; });
// primer par: 8

std::vector<int> sub = {2, 6};
auto finSub = std::find_end(datos.begin(), datos.end(),
                            sub.begin(), sub.end());
// índice de la última aparición de {2,6}

1.2 count y count_if

Cuentan ocurrencias.

std::array<int,6> arr = {1,2,2,3,2,4};
int cuantos2 = std::count(arr.begin(), arr.end(), 2);       // 3
int cuantosPares = std::count_if(arr.begin(), arr.end(),
                                 [](int x) { return x%2==0; }); // 4

1.3 for_each

Ejecuta una función sobre cada elemento (puede modificar si se pasa referencia).

std::deque<int> sec = {1,2,3,4};
std::for_each(sec.begin(), sec.end(), [](int &v) { v *= 2; });
// sec = {2,4,6,8}

1.4 equal y mismatch

Comparan rangos.

std::vector<int> a = {1,2,3};
std::vector<int> b = {1,2,4};
bool igual = std::equal(a.begin(), a.end(), b.begin());    // false
auto dif = std::mismatch(a.begin(), a.end(), b.begin());
// dif.first apunta a 3, dif.second a 4

1.5 all_of, any_of, none_of

std::vector<int> col = {2,4,6,8};
bool todosPares = std::all_of(col.begin(), col.end(),
                              [](int x) { return x%2==0; });  // true
bool algunImpar = std::any_of(...);                          // false
bool ningunNeg = std::none_of(...);                          // true

2. Algoritmos que modifican secuencias

2.1 copy y copy_if

std::vector<int> fuente = {1,2,3,4,5};
std::vector<int> destino(5);
std::copy(fuente.begin(), fuente.end(), destino.begin());

std::vector<int> pares;
std::copy_if(fuente.begin(), fuente.end(),
             std::back_inserter(pares), [](int x) { return x%2==0; });
// pares = {2,4}

2.2 transform

std::vector<int> entrada = {1,2,3};
std::vector<int> cuadrados(3);
std::transform(entrada.begin(), entrada.end(), cuadrados.begin(),
               [](int x) { return x*x; });

std::vector<int> v1 = {1,2,3}, v2 = {4,5,6}, suma(3);
std::transform(v1.begin(), v1.end(), v2.begin(), suma.begin(),
               std::plus<int>());

2.3 replace, replace_if, replace_copy

std::vector<int> nums = {1,2,3,2,5};
std::replace(nums.begin(), nums.end(), 2, 20);  // {1,20,3,20,5}
std::replace_if(nums.begin(), nums.end(),
                [](int x) { return x>10; }, 0); // {1,0,3,0,5}

std::vector<int> copia;
std::replace_copy(nums.begin(), nums.end(),
                  std::back_inserter(copia), 3, 300);
// copia = {1,0,300,0,5}

2.4 remove, remove_if y erase (borrado lógico y físico)

std::vector<int> datos = {1,2,3,2,4};
auto nuevoFinal = std::remove(datos.begin(), datos.end(), 2);
datos.erase(nuevoFinal, datos.end());  // {1,3,4}

datos = {1,2,3,4,5};
datos.erase(std::remove_if(datos.begin(), datos.end(),
                           [](int x) { return x%2==0; }),
            datos.end());  // {1,3,5}

2.5 unique

std::vector<int> rep = {1,1,2,2,3,3,3,4,5};
auto it = std::unique(rep.begin(), rep.end());
rep.erase(it, rep.end());  // {1,2,3,4,5}

2.6 reverse

std::list<int> lst = {1,2,3,4,5};
std::reverse(lst.begin(), lst.end());  // {5,4,3,2,1}

2.7 rotate

std::vector<int> v = {1,2,3,4,5};
std::rotate(v.begin(), v.begin()+2, v.end());
// {3,4,5,1,2}

2.8 shuffle

#include <random>
std::vector<int> v = {1,2,3,4,5};
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(v.begin(), v.end(), g);

3. Algoritmos de ordenación y búsqueda binaria

3.1 sort, stable_sort, partial_sort

std::vector<int> v = {5,3,1,4,2};
std::sort(v.begin(), v.end());                    // asc
std::sort(v.begin(), v.end(), std::greater<int>()); // desc

std::vector<std::pair<int,int>> par = {{1,2},{2,1},{1,1},{2,2}};
std::stable_sort(par.begin(), par.end(),
                 [](const auto &a, const auto &b) { return a.first < b.first; });

std::vector<int> v2 = {5,3,1,4,2,6};
std::partial_sort(v2.begin(), v2.begin()+3, v2.end());
// primeros 3: 1,2,3

3.2 nth_element

std::vector<int> v = {5,3,1,4,2,6};
std::nth_element(v.begin(), v.begin()+2, v.end());
// v[2] = 3, izquierda ≤3, derecha ≥3

3.3 binary_search, lower_bound, upper_bound

std::vector<int> ord = {1,3,3,5,7};
bool existe = std::binary_search(ord.begin(), ord.end(), 3); // true
auto lb = std::lower_bound(ord.begin(), ord.end(), 3);  // índice 1
auto ub = std::upper_bound(ord.begin(), ord.end(), 3);  // índice 3

3.4 merge

std::vector<int> a = {1,3,5}, b = {2,4,6};
std::vector<int> fusion(6);
std::merge(a.begin(), a.end(), b.begin(), b.end(), fusion.begin());
// {1,2,3,4,5,6}

4. Algoritmos de montículo (heap)

std::vector<int> h = {4,1,3,2,5};
std::make_heap(h.begin(), h.end());  // max-heap

h.push_back(6);
std::push_heap(h.begin(), h.end());

std::pop_heap(h.begin(), h.end());
int max = h.back(); h.pop_back();

std::sort_heap(h.begin(), h.end());  // asc

5. Mínimos y máximos

int minVal = std::min(5,3);                    // 3
int maxVal = std::max({4,2,8,5,1});            // 8

std::vector<int> v = {3,1,4,2,5};
auto minIt = std::min_element(v.begin(), v.end());  // apunta a 1
auto maxIt = std::max_element(v.begin(), v.end());  // apunta a 5
auto mm = std::minmax_element(v.begin(), v.end());
// mm.first → 1, mm.second → 5

6. Algoritmos numéricos (<numeric>)

6.1 accumulate

#include <numeric>
std::vector<int> v = {1,2,3,4,5};
int suma = std::accumulate(v.begin(), v.end(), 0);          // 15
int prod = std::accumulate(v.begin(), v.end(), 1,
                           std::multiplies<int>());         // 120

6.2 inner_product

std::vector<int> a={1,2,3}, b={4,5,6};
int dot = std::inner_product(a.begin(),a.end(),b.begin(),0); // 32

6.3 iota

std::vector<int> v(5);
std::iota(v.begin(), v.end(), 10); // {10,11,12,13,14}

6.4 partial_sum

std::vector<int> src={1,2,3,4,5}, dst(5);
std::partial_sum(src.begin(), src.end(), dst.begin()); // {1,3,6,10,15}

6.5 adjacent_difference

std::adjacent_difference(src.begin(), src.end(), dst.begin()); // {1,1,1,1,1}

7. Algoritmos adicionales

7.1 generate y generate_n

std::vector<int> v(5);
int n = 0;
std::generate(v.begin(), v.end(), [&n]() { return n++; }); // {0,1,2,3,4}

std::vector<int> w(5);
n = 10;
std::generate_n(w.begin(), 3, [&n]() { return n++; }); // {10,11,12,?,?}

7.2 includes

std::vector<int> v1={1,2,3,4,5}, v2={2,4};
bool ok = std::includes(v1.begin(),v1.end(),v2.begin(),v2.end()); // true

7.3 Operaciones de conjunto (en ordenación previa)

std::vector<int> v1={1,2,3,4,5}, v2={3,4,5,6,7}, res;
std::set_union(v1.begin(),v1.end(),v2.begin(),v2.end(),
               std::back_inserter(res)); // {1,2,3,4,5,6,7}
res.clear();
std::set_intersection(...); // {3,4,5}
res.clear();
std::set_difference(v1.begin(),v1.end(),v2.begin(),v2.end(),
                    std::back_inserter(res)); // {1,2}
res.clear();
std::set_symmetric_difference(...); // {1,2,6,7}

8. Notas prácticas en sistemas embebidos

  • sort usa introsort (inestable) y stable_sort mergesort (estable, mayor consumo de memoria). Preferir sort si el orden relativo no importa.
  • remove no reduce el tamaño del contenedor; debe combinarse con erase para liberar memoria. En sistemas con poca RAM, usar erase puede caussar reubicaciones costosas.
  • Algoritmos como binary_search y set_intersection requieren datos ordenados. Ordenar una vez y reutilizar reduce el consumo energético.
  • En microcontroladores sin excepciones ni RTTI, usar std::vector con precaución; a veces es mejor buffers estáticos.

Etiquetas: STL C++ algoritmos contenedores Ordenación

Publicado el 6-8 21:25