Implementar o algoritmo de classificação por inserção em C++
Este artigo demonstrará como implementar um algoritmo de classificação por inserção em C++.
Implementar a classificação por inserção para o recipiente std::vector
em C++
Neste guia, mostraremos como implementar a classificação por inserção como uma função separada que leva uma referência ao objeto std::vector
e modifica o conteúdo no local. A classificação por inserção itera por meio de cada elemento do vetor. Ele garante que todos os elementos antes da posição atual sejam classificados, comparando o elemento atual com os anteriores na ordem inversa.
Geralmente, a ordem de comparação não importa muito no desempenho do algoritmo, mas assumimos a ordem reversa e implementamos o código de forma correspondente. Também presumiremos que estamos classificando os elementos em ordem crescente. Ainda assim, em casos reais, o algoritmo de classificação genérico deve ser capaz de usar uma função de comparação personalizada como argumento. Observe que a operação de comparação freqüentemente força o elemento a ser deslocado para a direita se o elemento atual for menor que o anterior. A última operação é implementada usando outro loop for
aninhado, que invoca a função std::swap
em elementos que estão na ordem errada.
O trecho de código a seguir inclui a função insertionSort
em que o loop for
externo é responsável por toda a travessia do array. Inicializamos o iterador para o segundo elemento no vetor porque as próximas etapas incluem a comparação com as anteriores - o loop interno itera do elemento atual até o primeiro para compará-los. Se a função de comparação for avaliada como true
, o par é trocado. Observe que a expressão else
força o loop interno a quebrar quando pelo menos um elemento anterior acaba sendo menor que o elemento atual.
#include <algorithm>
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::vector;
template <typename T>
void printVector(const vector<T> &vec) {
for (auto &i : vec) {
cout << i << "; ";
}
cout << endl;
}
template <typename T>
void insertionSort(vector<T> &vec) {
for (auto it = vec.begin() + 1; it != vec.end(); ++it) {
auto key = it;
for (auto i = it - 1; i >= vec.begin(); --i) {
if (*i > *key) {
std::swap(*i, *key);
key--;
} else {
break;
}
}
}
}
int main() {
vector<int> vec1 = {43, 5, 123, 94, 359, -23, 2, -1};
printVector(vec1);
insertionSort(vec1);
printVector(vec1);
return EXIT_SUCCESS;
}
Resultado:
43;
5;
123;
94;
359;
- 23;
2;
- 1;
- 23;
- 1;
2;
5;
43;
94;
123;
359;
Alternativamente, podemos reimplementar a função insertionSort
usando construções de loop while
se a última for preferida como uma forma mais legível para o usuário. Dois algoritmos seguem uma lógica de implementação semelhante e ambos utilizam a função std::swap
para deslocar os elementos. A classificação por inserção é um algoritmo bastante ineficiente em grandes conjuntos de dados e seu desempenho médio é O (n2).
A ordenação por inserção é semelhante a outro algoritmo quadrático denominado ordenação por seleção; ambos iteram por meio do vetor. Após as iterações n
, os primeiros elementos n
são classificados. Embora, a classificação de seleção avalie os elementos para frente da posição atual em contraste com a classificação de inserção.
#include <algorithm>
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::vector;
template <typename T>
void printVector(const vector<T> &vec) {
for (auto &i : vec) {
cout << i << "; ";
}
cout << endl;
}
template <typename T>
void insertionSort2(vector<T> &vec) {
auto iter = vec.begin() + 1;
while (iter != vec.end()) {
auto key = iter;
auto it = iter - 1;
while (it >= vec.begin() && *it > *key) {
std::swap(*it, *key);
key--;
it--;
}
iter++;
}
}
int main() {
vector<int> vec1 = {43, 5, 123, 94, 359, -23, 2, -1};
printVector(vec1);
insertionSort2(vec1);
printVector(vec1);
return EXIT_SUCCESS;
}
Resultado:
43;
5;
123;
94;
359;
- 23;
2;
- 1;
- 23;
- 1;
2;
5;
43;
94;
123;
359;
A classificação por inserção pode ser mais eficiente na prática em comparação com outros algoritmos O (n2) porque nem sempre é necessário comparar o elemento atual com todos os anteriores. Enquanto isso, a classificação de seleção deve sempre pesquisar cada elemento no subarray não classificado para encontrar o menor (ou o maior) elemento. Observe que podemos utilizar a implementação da função insertionSort
no vetor de std::string
como a última classe implementa as sobrecargas do operador de comparação. O próximo exemplo demonstra seu uso básico com o vetor string e imprime a lista classificada de palavras.
#include <algorithm>
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::vector;
template <typename T>
void printVector(const vector<T> &vec) {
for (auto &i : vec) {
cout << i << "; ";
}
cout << endl;
}
template <typename T>
void insertionSort(vector<T> &vec) {
auto iter = vec.begin() + 1;
while (iter != vec.end()) {
auto key = iter;
auto it = iter - 1;
while (it >= vec.begin() && *it > *key) {
std::swap(*it, *key);
key--;
it--;
}
iter++;
}
}
int main() {
vector<string> vec2 = {"highway", "song", "work",
"borland", "death", "woman"};
printVector(vec2);
insertionSort(vec2);
printVector(vec2);
return EXIT_SUCCESS;
}
Resultado:
highway;
song;
work;
borland;
death;
woman;
borland;
death;
highway;
song;
woman;
work;
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook