1. Algoritmos de inspección (no modificadores)
Estos procedimientos analizan el contanido de un contenedor sin alterar los elementos existentes.
1.1 Búsqueda con find y find_if
find: Localiza la primera coincidencia de un valor específico.find_if: Busca el primer elemento que cumpla con una condición lógica (predicado).
#include <vector>
#include <algorithm>
#include <iostream>
std::vector<int> valores = {10, 20, 30, 40, 50};
// Localizar un valor exacto
auto it = std::find(valores.begin(), valores.end(), 30);
if (it != valores.end()) {
std::cout << "Encontrado: " << *it << std::endl;
}
// Buscar el primer múltiplo de 7
auto it_cond = std::find_if(valores.begin(), valores.end(), [](int n) {
return n % 7 == 0;
});
// it_cond será valores.end() si no hay coincidencias
1.2 Conteo con count y count_if
Permiten obtener la frecuencia de aparición de elementos según criterios definidos.
std::vector<int> datos = {1, 2, 2, 3, 4, 2, 5};
int total_doses = std::count(datos.begin(), datos.end(), 2); // Resultado: 3
int mayores_que_tres = std::count_if(datos.begin(), datos.end(), [](int x) {
return x > 3;
}); // Resultado: 2
1.3 Verificación de predicados: all_of, any_of, none_of
Útiles para validaciones rápidas sobre rangos de datos.
std::vector<int> lista = {2, 4, 6, 8};
bool todos_pares = std::all_of(lista.begin(), lista.end(), [](int n) { return n % 2 == 0; });
bool algun_negativo = std::any_of(lista.begin(), lista.end(), [](int n) { return n < 0; });
bool ningun_cero = std::none_of(lista.begin(), lista.end(), [](int n) { return n == 0; });
2. Algoritmos de modificación de secuencias
Estas funciones alteran el orden, el valor o la estructura de los datos en el contenedor.
2.1 Transformación de datos
transform aplica una operación a cada elemento y almacena el resultado en un destino.
std::vector<int> entrada = {1, 2, 3, 4};
std::vector<int> salida;
// Calcular el cubo de cada número
std::transform(entrada.begin(), entrada.end(), std::back_inserter(salida), [](int n) {
return n * n * n;
});
2.2 El modismo Erase-Remove
En C++, remove no elimina físicamente los elementos del contenedor (no cambia el tamaño), solo los desplaaz. Es necesario usar el método erase para limpiar el contenedor.
std::vector<int> nums = {10, 20, 30, 20, 40, 20};
// Mover los '20' al final y obtener el nuevo iterador final
auto nuevo_final = std::remove(nums.begin(), nums.end(), 20);
// Eliminar físicamente los elementos sobrantes
nums.erase(nuevo_final, nums.end());
// nums ahora es {10, 30, 40}
2.3 Reemplazo de valores
Sustituye elementos que coincidan con un valor o condición por uno nuevo.
std::vector<int> serie = {1, 5, 8, 5, 2};
std::replace(serie.begin(), serie.end(), 5, 99);
// serie: {1, 99, 8, 99, 2}
3. Ordenamiento y búsqueda binaria
Para utilizar algoritmos de búsqueda eficiente, la secuencia debe estar previamente ordenada.
3.1 Tipos de ordenamiento
sort: Ordenamiento rápido (complejidad promedio O(N log N)).stable_sort: Mantiene el orden relativo de elementos equivalentes.partial_sort: Ordena solo los primeros N elementos.
std::vector<int> desorden = {9, 1, 5, 3, 7};
std::sort(desorden.begin(), desorden.end()); // {1, 3, 5, 7, 9}
3.2 Búsqueda en rangos ordenados
std::vector<int> ordenados = {10, 20, 20, 30, 40};
// lower_bound: primer elemento >= 20
auto lb = std::lower_bound(ordenados.begin(), ordenados.end(), 20);
// upper_bound: primer elemento > 20
auto ub = std::upper_bound(ordenados.begin(), ordenados.end(), 20);
bool existe = std::binary_search(ordenados.begin(), ordenados.end(), 30);
4. Algoritmos numéricos
Ubicados en la cabecera <numeric>, facilitan operaciones matemáticas sobre colecciones.
4.1 Acumulación e iota
#include <numeric>
std::vector<int> v(5);
// Llenar con 10, 11, 12, 13, 14
std::iota(v.begin(), v.end(), 10);
// Sumar todos los elementos comenzando desde 0
int suma = std::accumulate(v.begin(), v.end(), 0);
4.2 Diferencias adyacentes
std::vector<int> sec = {1, 2, 4, 7, 11};
std::vector<int> difs(sec.size());
std::adjacent_difference(sec.begin(), sec.end(), difs.begin());
// difs: {1, 1, 2, 3, 4}
5. Gestión de estructuras de Montículo (Heap)
Permite tratar un contenedor como un árbol binario donde el elemento máximo siempre está en la raíz.
std::vector<int> heap_data = {10, 50, 20, 40, 30};
std::make_heap(heap_data.begin(), heap_data.end());
// El máximo (50) está ahora en heap_data[0]
heap_data.push_back(60);
std::push_heap(heap_data.begin(), heap_data.end()); // Reordena para incluir 60
std::pop_heap(heap_data.begin(), heap_data.end()); // Mueve el máximo al final
heap_data.pop_back(); // Elimina el antiguo máximo
Preguntas Frecuentes
- ¿Cuándo usar stable_sort sobre sort? Use
stable_sortcuando el orden original de elementos con claves idénticas deba preservarse, por ejemplo, al ordenar una lista de usuarios por apellido que ya estaba ordenada por nombre. - ¿Por qué remove no borra los elementos? Los algoritmos de la STL operan sobre iteradores y no tienen conocimiento directo de la estructura interna del contenedor (como su capacidad o tamaño). Por ello, solo pueden mover valores; la gestión de memoria queda a cargo del contenedor mediante
erase. - ¿Qué algoritmos requieren datos ordenados? Principalmente
binary_search,lower_bound,upper_bound,equal_range,merge,includesy las operaciones de conjuntos (set_union,set_intersection, etc.).