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

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Este site utiliza o Akismet para reduzir spam. Saiba como seus dados em comentários são processados.