Você está na página 1de 6

Ordenação por seleção – Selection Sort

Evandro Mafort, Gabriel Rodrigues, Lorran Fernandes da C. Parreira

Afinal, o que é o Selection Sort?

A Ordenação por Seleção, ou Selection Sort, é um dos algoritmos mais simples para utilizarmos
ao ordenar listas de elementos, em qualquer linguagem. Consiste em basicamente montar dois
laços de repetição, sendo o primeiro o iterador – chamemos ele de i - sobre a lista em si (do
primeiro ao penúltimo item) e o segundo – chamemos de j - irá iterar a partir de um menor
elemento do vetor, partindo da próxima posição após o índice i. Dentro do laço j, a iteração
funciona da seguinte forma: O algoritmo verifica se o elemento atual – vetor[i] – é menor que
o elemento encontrado até aquele momento – vetor[menor]. Se sim, o índice desse elemento
é atualizado para j e o contador de comparações é incrementado em uma unidade,
independente se a comparação for falsa ou verdadeira. Após concluir o loop interno, o
algoritmo verifica se o índice do menor elemento é diferente do índice atual (i). Se forem
diferentes, isso indica que um elemento menor foi encontrado e, portanto, realiza a troca
entre o elemento atual (vetor[i]) e o elemento encontrado (vetor[menor]). Ao final do laço de
comparações, é chamada uma variável auxiliar para receber o valor de vetor[i], seguindo a
partir disso operações que trocam os valores de lugar, assim como atualizando o contador de
movimentações – o incrementando em 2.

Como podemos observar, a operação em si é mais simples (sendo a parte dos laços for
aninhados a parte mais difícil de entender de cara), parte da ação se parecendo muito com
exercícios simples de construção de algoritmos (a troca dos valores utilizando variável auxiliar).

E como surgiu o Selection Sort?

A história da criação e desenvolvimento do Selection Sort é um tanto quanto nebulosa.


Se olhamos a simplicidade do algoritmo, podemos inferir que a criação do mesmo se deu antes
da criação dos computadores como entendemos ele, dada a sua simplicidade estrutural em
ordenar conjuntos de coisas em ordem (seja ela crescente ou decrescente). Como não há um
nome em específico para determinar como o criador do Selection Sort, mas apenas registros
de uso ou desenvolvimento da ideia de forma aplicada, podemos citar o trabalho do
engenheiro Herman Hollerith (um dos fundadores da IBM), que nos anos 20 criou uma forma
de poder ordenar dados do Censo americano – dado o volume titânico de informação e a
quantidade de tempo homérica pra execução da atividade – por fim criando uma máquina que
pudesse fazer essa tarefa de ordenação dos dados.

Passadas algumas décadas, já dentro da computação, talvez a descrição mais


importante (e uma das primeiras, senão a primeira) seja a de Donald Knuth, cientista da
computação e ganhador do Prêmio Turing de 1974, que descreve o algoritmo em detalhes,
seus usos, vantagens, desvantagens e complexidade, no primeiro volume de sua obra de
quatro livros, The Art Of Computer Programming – publicado primeiramente em 1968.

E quanto a complexidade do Selection Sort?

A complexidade do Selection Sort pode ser entendida da seguinte forma: O algoritmo


em questão utiliza dois laços for: O laço i – O(n) – e o laço j – O(n). Matematicamente, temos:

O(n) * O(n) = O(n*n) = O(N²)


Portanto, a complexidade do Selection Sort é O(N²). Podemos também estender a
compreensão da complexidade para a variável auxiliar – na hora da troca de valores – como
O(1) e, além disso, outro dado que tange a complexidade do Selection Sort é que a
complexidade nunca passa de O(n) passos, o que o torna um algoritmo bom de ser usado
quando a memória não pode ser desperdiçada.

E quais são as vantagens e desvantagens de utilizar Selection Sort?

Assim como tudo na vida, há vantagens e desvantagens em utilizar o Selection Sort.


Falando em vantagens, temos que o algoritmo em questão é simples de entender e
implementar, sendo uma ótima escolha utilizá-lo para introduzir o conceito de processamento
de dados. Outra vantagem do Selection Sort é a quantidade de trocas de elementos,
mantendo a menor quantidade possível - com relação a outros algoritmos de processamento -
em operações que trazem um custo grande de memória e processamento.

Quanto as desvantagens, temos que, primeiramente, o algoritmo possui complexidade


O(n²). Ou seja: Quanto maior for a estrutura, mais tempo de processamento irá levar – isso
falando em termos de caso médio e pior caso. Com isso, temos uma falha derivada: É
impraticável utilizar esse algoritmo, por conta da quantidade de passos. Se um dataset possuir
muitas entradas – na casa dos milhares, por exemplo – o número de movimentações também
poderá seguir com a mesma quantidade, aproximadamente, de movimentos dentro do
algoritmo, dependendo de como os dados iniciais estão organizados.

Uma desvantagem que pode ser contornada é o fato de o algoritmo em questão não
ser estável para ordenar arrays com chaves iguais (por exemplo, um array que apresente a
forma [4A,5,3,2,4B,1]). Porém, o Selection Sort pode ser estabilizado alterando a operação de
comparação de chave para que a comparação de duas chaves considere a posição como um
fator para objetos com chave igual ou o ajustando de forma que o significado da chave não
mude, o tornando estável.

E quanto a eficiência do Selection Sort?

Comparado a outros algoritmos que fazem a mesma tarefa, o Selection Sort leva a
pior, por conta da sua complexidade O(n²). Ainda há uma certa vantagem em utilizar este
algoritmo, por conta da quantidade de passos necessários e se o foco do uso for simplicidade
na hora de escrever o código, mas deve-se evitá-lo quando se busca eficiência. Outros
algoritmos, como o Merge Sort, Quick Sort ou Heap Sort, que possuem complexidade O(n log
n) ou até O(n) – dependendo do caso. Mesmo o seu uso em um cenário de melhor caso não
melhora as coisas, já que a quantidade de memória gasta pode ser um entrave. A eficiência
deste algoritmo, como dito antes, se mostra quando o conjunto de dados a ordenar é simples
e relativamente pequeno, uma mão na roda nesses casos.

Exemplo de aplicação/implementação do algoritmo:

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#define tam 9

void preencherVetor(int vetor[], int tamanho)


{

int i;

for (i = 0; i < tamanho; i++)

vetor[i] = (rand() % 9) + 1;

void selectionSort(int vetor[], int tamanho, int *comparacoes, int *movimentacoes)

int i, j, auxiliar, menor;

for (i = 0; i < tamanho - 1; i++)

menor = i;

for (j = i + 1; j < tamanho; j++)

if (vetor[j] < vetor[menor])

menor = j;

*comparacoes +=1;

if (i != menor)

auxiliar = vetor[i];

vetor[i] = vetor[menor];

*movimentacoes +=1;

vetor[menor] = auxiliar;

*movimentacoes +=1;

int main()

{
int i, v[tam];

int movimentacoes = 0, comparacoes = 0;

srand(time(NULL));

preencherVetor(v, tam);

printf("Vetor inicial:\t ");

for (i = 0; i < tam; i++)

printf("%d\t", v[i]);

selectionSort(v, tam, &comparacoes, &movimentacoes);

printf("\n\nVetor ordenado:\t ");

for (i = 0; i < tam; i++)

printf("%d\t", v[i]);

printf("\nNumero de movimentacoes: %d\tNumero de comparacoes: %d\n",


movimentacoes, comparacoes);

return 0;

Observações:

1. Diferente de outros códigos, neste foi usado uma função responsável por preencher o vetor

automaticamente a fim de facilitar a implementação de vetores com tamanhos variados.

2. srand(time(NULL)) é uma chamada de função presente na biblioteca time.h e é usada para


inicializar a semente do gerador de números aleatórios e impedir que os números sorteados
sejam sempre os mesmos.

Descrição do funcionamento:

O algoritmo é composto por 2 laços for. O primeiro é responsável por cuidar do índice inicial e
o segundo por percorrer o vetor. Inicialmente, o primeiro laço inicializa o índice com o valor 0
e é adicionado 1 unidade a cada iteração. Já o segundo percorre o vetor começando do índice
inicial + 1 a fim de achar um elemento que seja menor que o presente na posição inicial, caso
tenha.

A seguir um exemplo para melhor compreensão:

Vetor:

O índice inicial é 0 e o laço mais interno começa da posição 1 (índice inicial + 1) e percorre o
vetor até achar o menor elemento, neste caso o número zero. Assim, pelo fato de os dois
índices serem diferentes, o zero troca de posição com o elemento nove.
Após o término do segundo laço, 1 unidade é incrementada ao primeiro laço e o loop mais
interno começa do índice 2. Dito isso, o processo de comparações é iniciado e o elemento um
troca de posição com o elemento sete após ser verificado que ele é o segundo menor número
do vetor.

Continuando o mesmo procedimento, 1 unidade é incrementada ao primeiro laço e o loop


mais interno começa do índice 3. Como resultado, encontramos o menor elemento no índice
4, o qual troca de posição com o elemento no índice 2.

Mais 1 unidade é incrementada ao primeiro laço e o loop mais interno começa do índice 4.
Após comparações, o quarto menor elemento é encontrado no último índice e troca de
posição com o elemento sete.

Mais 1 unidade é incrementada ao primeiro laço e o loop mais interno começa do índice 5.
Finalizado o for, o menor elemento encontrado é o 7, o qual muda de posição com o elemento
8.

Mais 1 unidade é incrementada ao primeiro laço e o loop mais interno começa do índice 6.
Como conclusão, o menor elemento restante é o 8, o qual muda de posição com o elemento 9,
o maior deste vetor.

Consequentemente, podemos calcular o número de comparações que ocorreram a partir do


seguinte cálculo: (n2 – n) / 2 e de movimentações considerando que sempre ocorrem 2 vezes
dentro de uma troca. Dessa forma, os valores 21 e 12 são obtidos.
BIBLIOGRAFIA

https://www.geeksforgeeks.org/selection-sort/

https://www.geeksforgeeks.org/stable-selection-sort/

https://pt.slideshare.net/DanielArndtAlves/selection-sort-25735943

https://link.springer.com/chapter/10.1007/978-3-540-77978-0_5

(todos os links acessados em 28/5/2023)

Você também pode gostar