Um dos problemas básicos em Computação é, considerando uma certa relação de ordem,
ordenar um conjunto de valores. Aqui são mostrados dois métodos de ordenação:
inserção e seleção.
De forma mais específica, dado o arranjo:
int a[]={50,20,30,10,40};
deseja-se organizar o arranjo de forma a obter: 10, 20, 30, 40, 50 (ou a ordem
inversa). Uma das formas de se obter isso é mudar o contéudo do arranjo: nos
elementos de menor índice ficam os menores valores e nos elementos de maior
índice ficam os maiores valores. Isto significa que o arranjo fica ordenado em
ordem crescente segundo a ordem dos índices.
Um dos métodos mais simples de ordenação é a seleção: encontre o menor valor
em um arranjo e troque a posição dele com o valor que está na primeira posição,
depois encontre o segundo menor valor e troque a posição dele com o valor na segunda
posição. No caso do exemplo acima teriamos os seguintes passos:
arranjo dado: {50,20, 30, 10, 40}
1o. passo {10, 20, 30, 50, 40}
2o. passo {10, 20, 30, 50, 40}
3o. passo {10, 20, 30, 50, 40}
4o. passo {10, 20, 30, 40, 50}
A função abaixo mostra uma sugestão de implementação da ordenação por
seleção:
void ordenaPorSelecao(int a[],
int N){
int i,j,aux,indMenor;
for(i=0; i<N-1; i++){ //iteracao de cada posicao
indMenor=i;
for(j=i+1; j<N; j++) //iteracao para selecionar
[indice do] menor
if(a[j]<a[indMenor]) indMenor=j;
aux=a[i];
a[i]=a[indMenor];
a[indMenor]=aux;
}
}
A função ordenaPorSelecao() recebe um ponteiro para um arranjo de inteiros (lembre-se que int a[] equivale a int *a) e utiliza a idéia descrita acima para a ordenação. A execução fica estruturada sob dois comandos for. O for mais externo marca qual parte do arranjo já foi ordenada, o for mais interno varre a parte restante do arranjo para determinar o índice do menor elemento. Num dado momento da execução, o arranjo já se encontra ordenado da posição de índice 0 até a posição de índice i-1.
Outra idéia de ordenação dá origem ao algoritmo de ordenação por inserção.
Considere somente um primeiro valor: ele já está ordenado. Considere dois
valores: (i)eles já estão ordenados ou (ii)devemos deslocar um valor para dar
lugar para o outro. A cada novo passo consideramos um novo elemento e achamos
no arranjo, já parcialmente ordenado, onde ele deve ficar (em função de termos
“arredado” os elementos que ainda não estão em lugar adequado. No caso do
exemplo acima teriamos os seguintes passos:
arranjo dado: {50,20, 30, 10, 40}
1o. passo: {20,50,30,10,40}
2o. passo: {20,30,50,10,40}
3o. passo: {10,20,30,50,40}
4o. passo: {10,20,30,40,50}
A função abaixo mostra uma sugestão de implementação da ordenação por inserção:
void ordenaPorInsercao(int
a[], int N){
int i,j, aux;
for(i=1; i<N; i++){ //iteracao de cada posição
aux=a[i];
j=i;
while(j>0&&a[j-1]>aux)
a[j]=a[--j]; //iteracao de “arredar”
a[j]=aux;
}
}
No caso da função acima, temos dois comandos iterativos aninhados: um while dentro de um for. A cada iteração do for é considerado um novo elemento do arranjo. O while envolve duas condições (j>0) e (a[j-1]>aux): a primeira condição relaciona-se com o elemento considerado ser o menor de todos que já estão ordenados (j já atingiu 0 e o “arredamento” deve terminar), a segunda condição relaciona-se com o elemento considerado ser colocado em algum local do arranjo com índice j>0. A sugestão de implementação acima utiliza o seguinte comando de atribuição ) a[j]=a[--j];. O uso da atribuição ) a[j]=a[--j]; não é recomendado em função de depender da ordem de avaliação das expressões correspondentes às indexações do arranjo. Nos exercícios abaixo é pedida uma implementação menos arriscada
Exercícios:
int[] a={50,20,30,10,40};
int[]
ind=permutacaoDeOrdenacaoPorSelecao(a,5);
for(i=0; i<5; i++)
printf(“%d\n”,a[ind[i]]);
int *permutacaoDeOrdenacaoPorSelecao(int[] a, int T){
int *ai=(int*)malloc(sizeof(int)*T);
int i;
for(i=0; i<T; i++) ai[i]=i;
...
return ai;
No caso do arranjo acima a permutação que o ordena é
{3,1,2,4,0}.