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_sortmantém a ordem relativa de elementos iguais, enquantosortpadrão não. - Modificação e Tamanho: Algoritmos como
removeapenas reorganizam elementos e retornam um novo fim lógico. Para alterar o tamanho do contêiner, combine comerase. - 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.