Utilização da função QSort em C
A função qsort() é uma função em C utilizada para ordenação de arrays. O protótipo da função é void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*)), onde base é um ponteiro para o primeiro elemento do array, nitems é o número de elementos do array, size é o tamanho em bytes de cada elemento do array e compar é a função criada para o problema e que compara dois elementos.
Os três primeiros parâmetros são simples de fornecer, mas o último exige maior atenção. Ele consiste de um ponteiro para uma função que é responsável por comparar dois valores fornecidos como parâmetro para a função. Essa função deverá retornar:
- Valor maior do que zero: se o primeiro valor for maior do que o segundo.
- Valor menor do que zero: se o primeiro valor for menor do que o segundo.
- Zero: se os valores forem iguais.
Pode parecer estranho ter que fazer uma função que compara valores porque normalmente pensamos em um array com números, mas e se for fornecido um array de valores enumerados, ou um array de alguma struct? Sendo assim, a função qsort() pode ser utilizada para qualquer tipo de dado e por isso ela utiliza um ponteiro void como base e é preciso elaborar uma função que explica como fazer a comparação.
O código a seguir exemplifica o uso da função qsort() em um array. São mostradas duas funções para comparação, mas que apresentam o mesmo resultado.
A função comparador() recebe dois números do array e os compara. Veja que a função recebe dois ponteiros void e por isso é preciso fazer o cast para o tipo de dado do array, no caso, valores inteiros. Veja também que, em vez de fazer uma comparação com o uso do if, foi utilizado simplesmente uma subtração dos valores. Se o valor de “a” for maior do que o valor de “b”, então o resultado será maior do que zero significando que o primeiro valor é maior do que o segundo. A função comparador2() faz as comparações utilizando o desvio condicional if.
#include <stdio.h>
#include <stdlib.h>
int comparador(const void *a, const void *b) {
return ( *(int*)a - *(int*)b );
}
int comparador2(const void *a, const void *b) {
if (*(int*)a > *(int*)b) {
return 1;
} else if (*(int*)a < *(int*)b) {
return -1;
} else {
return 0;
}
}
int main () {
int i, val[] = { 15, 30, 10, 20, 25 };
//ordena o array
qsort(val, 5, sizeof(int), comparador);
//mostra os valores do array
for( i = 0 ; i < 5; i++ ) {
printf("%i ", val[i]);
}
return(0);
}
Experimente o código online em: https://ideone.com/JwgKmn
Veja que a função comparador é a responsável por determinar a ordem dos elementos. Da maneira como é determinado o valor de retorno, ela fará a ordenação de forma crescente dos valores do array. Se eu inverter as variáveis “a” e “b” na operação, fazendo *(int*)b – *(int*)a, isso fará com que o vetor passe a ser ordenado de forma decrescente.
Como comentado, a função qsort() pode ser utilizada para comparar qualquer tipo de dado. O código abaixo mostra sua utilização para ordenar um array de structs. Duas funções de comparação são especificadas. Uma é responsável por ordenar as pessoas por idade e a outra por ordenar em ordem alfabética o nome das pessoas.
#include <stdio.h>
#include <stdlib.h>
struct pessoa {
char nome[20];
int idade;
};
int compararIdade (const void *x, const void *y) {
int pri = ((struct pessoa *)x)->idade;
int seg = ((struct pessoa *)y)->idade;
return (pri - seg);
}
int compararNome (const void *a, const void *b) {
return strcmp (((struct pessoa *)a)->nome,((struct pessoa *)b)->nome);
}
int main () {
int i;
int idades[]={9,7,8,5,2};
char nomes[][20] = {"Joao","Pedro","Ana","Maria","Teste"};
struct pessoa item[5];
printf("Pessoas sem ordem:\n");
for (i = 0; i < 5; i++) {
strcpy(item[i].nome, nomes[i]);
item[i].idade = idades[i];
printf("%s: %d\n", item[i].nome, item[i].idade);
}
qsort(item, 5, sizeof(struct pessoa), compararIdade);
printf("Pessoas ordenadas por idade:\n");
for (i = 0; i < 5; i++) {
printf("%s: %d\n", item[i].nome, item[i].idade);
}
qsort(item, 5, sizeof(struct pessoa), compararNome);
printf("Pessoas ordenadas por nome:\n");
for (i = 0; i < 5; i++) {
printf("%s: %d\n", item[i].nome, item[i].idade);
}
return(0);
}
Experimente o código online em: https://ideone.com/IGk2Jv