Guia Completo dos Algoritmos da Biblioteca Padrão de Templates (STL) do C++

Algoritmos de Sequência Não Modificadores

Estes algoritmos não alteram os elementos nos intervalos que operam.

Localização: find, find_if, find_end

Para localizar elementos específicos ou subsequências em um contêiner.

vector<int> numeros = {10, 25, 30, 15, 40};
auto iterador = find(begin(numeros), end(numeros), 30);
if (iterador != end(numeros)) {
    cout << "Valor encontrado: " << *iterador << endl;
}
auto iteradorPar = find_if(begin(numeros), end(numeros), [](int n) {
    return n % 2 == 0;
});
cout << "Primeiro par: " << *iteradorPar << endl; // 30

Contagem: count, count_if

Para contar a ocorrência de elementos que satisfazem uma condição.

vector<int> dados = {5, 2, 8, 2, 9, 2};
int totalDeDois = count(begin(dados), end(dados), 2);
int totalPares = count_if(begin(dados), end(dados), [](int v) {
    return v % 2 == 0;
}); // Resultado: 4

Aplicação de Função: for_each

Para executar uma operação em cada elemento de um intervalo.

vector<double> valores = {1.5, 2.5, 3.5};
for_each(begin(valores), end(valores), [](double& v) {
    v *= 10.0; // Multiplica cada valor por 10
});
// valores agora contém: {15.0, 25.0, 35.0}

Comparação: equal, mismatch

Para comparar dois intervalos elemento a elemento.

vector<int> seqA = {1, 2, 3};
vector<int> seqB = {1, 4, 3};
bool iguais = equal(begin(seqA), end(seqA), begin(seqB)); // false
auto parDiferente = mismatch(begin(seqA), end(seqA), begin(seqB));
cout << "Diferença em: " << *parDiferente.first << " vs " << *parDiferente.second << endl; // 2 vs 4

Verificação Condicional: all_of, any_of, none_of

Para testar propriedades lógicas sobre um intervalo.

vector<int> nums = {2, 4, 6, 8};
bool todosPositivos = all_of(begin(nums), end(nums), [](int n){ return n > 0; }); // true
bool algumNegativo = any_of(begin(nums), end(nums), [](int n){ return n < 0; }); // false
bool nenhumZero = none_of(begin(nums), end(nums), [](int n){ return n == 0; }); // true

Algoritmos de Sequência Modificadores

Estes algoritmos modificam os elementos nos intervalos que operam.

Cópia: copy, copy_if

Para copiar elementos, opcionalmente filtrando por um predicado.

vector<int> origem = {10, 15, 20, 25, 30};
vector<int> destino;
copy_if(begin(origem), end(origem), back_inserter(destino), [](int v) {
    return v > 18;
});
// destino contém: {20, 25, 30}

Transformação: transform

Para aplicar uma operação a cada elemento e armazenar o resultado.

vector<int> base = {2, 3, 4};
vector<int> resultados(3);
transform(begin(base), end(base), begin(resultados), [](int x) {
    return x * x; // Calcula o quadrado
}); // resultados: {4, 9, 16}

Substituição: replace, replace_if, replace_copy_if

Para substituir valores com base em igualdade ou condição.

vector<string> frutas = {"maçã", "banana", "laranja", "banana"};
replace(begin(frutas), end(frutas), string("banana"), string("pêra"));
// frutas: {"maçã", "pêra", "laranja", "pêra"}

vector<int> idades = {12, 25, 17, 30, 14};
vector<int> maioresDeIdade;
replace_copy_if(begin(idades), end(idades), back_inserter(maioresDeIdade),
    [](int idade){ return idade < 18; }, 0); // Substitui menores por 0 na cópia

Remoção: remove, remove_if (Erasa)

Para "remover" elementos movendo-os para o final. Requer combinação com erase para remoção física.

vector<int> lista = {1, 4, 2, 5, 3, 4};
auto novoFim = remove_if(begin(lista), end(lista), [](int v){ return v > 4; });
lista.erase(novoFim, end(lista)); // lista agora: {1, 4, 2, 3, 4}
// Atualização: remove os 4s restantes
lista.erase(remove(begin(lista), end(lista), 4), end(lista)); // lista: {1, 2, 3}

Eliminação de Duplicatas: unique

Para remover duplicatas adjacentes. Geralmente usado após sort e com erase.

vector<int> numeros = {1, 2, 2, 3, 3, 3, 1};
sort(begin(numeros), end(numeros)); // {1, 1, 2, 2, 3, 3, 3}
auto novoFim = unique(begin(numeros), end(numeros));
numeros.erase(novoFim, end(numeros)); // numeros: {1, 2, 3}

Outras Modificações: reverse, rotate, shuffle

vector<int> dados = {1, 2, 3, 4, 5};
reverse(begin(dados), end(dados)); // {5, 4, 3, 2, 1}
rotate(begin(dados), begin(dados) + 2, end(dados)); // Rotaciona para {3, 2, 1, 5, 4}
// Para shuffle, é necessário um gerador aleatório
random_device rd;
mt19937 g(rd());
shuffle(begin(dados), end(dados), g);

Algoritmos de Ordenação e Pesquisa

Ordenação: sort, stable_sort, partial_sort

vector<int> vec = {5, 3, 1, 4, 2};
sort(begin(vec), end(vec)); // {1, 2, 3, 4, 5}
// stable_sort preserva a ordem relativa de elementos iguais.
// partial_sort: ordena apenas os N primeiros elementos.

Pesquisa em Dados Ordenados

Algoritmos como binary_search, lower_bound e upper_bound requerem intervalos ordenados.

vector<int> ordenado = {10, 20, 30, 40, 50};
bool existe = binary_search(begin(ordenado), end(ordenado), 30); // true
auto posInferior = lower_bound(begin(ordenado), end(ordenado), 25); // Aponta para 30
auto posSuperior = upper_bound(begin(ordenado), end(ordenado), 30); // Aponta para 40

União: merge

Para combinar dois intervalos ordenados em um terceiro intervalo ordenado.

vector<int> conjuntoA = {1, 3, 5};
vector<int> conjuntoB = {2, 4, 6};
vector<int> uniao(6);
merge(begin(conjuntoA), end(conjuntoA), begin(conjuntoB), end(conjuntoB), begin(uniao));
// uniao: {1, 2, 3, 4, 5, 6}

Algoritmos Numéricos

Funções para cálculos matemáticos em intervalos.

Acumulação: accumulate

#include <numeric>
vector<int> valores = {1, 2, 3, 4};
int soma = accumulate(begin(valores), end(valores), 0); // 10
int produto = accumulate(begin(valores), end(valores), 1, multiplies<int>()); // 24

Produto Interno: inner_product

vector<int> v1 = {1, 2, 3};
vector<int> v2 = {4, 5, 6};
int ponto = inner_product(begin(v1), end(v1), begin(v2), 0); // 1*4 + 2*5 + 3*6 = 32

Outros: iota, partial_sum, adjacent_difference

vector<int> sequencia(5);
iota(begin(sequencia), end(sequencia), 100); // {100, 101, 102, 103, 104}

vector<int> acumulados;
partial_sum(begin(sequencia), end(sequencia), back_inserter(acumulados)); // Somas parciais

vector<int> diferencas;
adjacent_difference(begin(sequencia), end(sequencia), back_inserter(diferencas)); // Diferenças entre adjacentes

Algoritmos de Conjuntos e Geração

Operações de Conjunto

Requerem intervalos ordenados.

vector<int> s1 = {1, 2, 3, 4, 5};
vector<int> s2 = {3, 4, 5, 6, 7};
vector<int> resultado;

set_union(begin(s1), end(s1), begin(s2), end(s2), back_inserter(resultado));
// resultado: {1, 2, 3, 4, 5, 6, 7}

Geração de Valores: generate, gneerate_n

Para preencher um intervalo com valores gerados por uma função.

vector<int> gerados(5);
int contador = 1;
generate_n(begin(gerados), 3, [&contador]() { return contador++; }); // {1, 2, 3, 0, 0}

Considerações de Uso

  • Estabilidade: stable_sort mantém a ordem relativa de elementos iguais, enquanto sort padrão não.
  • Modificação e Tamanho: Algoritmos como remove apenas reorganizam elementos e retornam um novo fim lógico. Para alterar o tamanho do contêiner, combine com erase.
  • Pré-requisitos: Algoritmos de pesquisa binária (binary_search, lower_bound, upper_bound) e operações de conjunto (merge, set_union) exigem que os intervalos de entrada estejam ordenados.

Tags: C++ STL Algoritmos Programação Genérica templates

Publicado em 6-17 18:01