[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Esse capítulo descreve funções para ordenação de dados, tanto direta quanto indireta (usando um índice). Todas as funções usam o algoritmo heapsort. A ordenação por partes (32)é um algoritmo O(N \log N) que opera localmente e não requer qualquer armazenamento adicional. Essa ausência de armazenamento adicional também fornece performace consistente, o tempo de execução para seu pior caso (dados ordenados) sendo não significativamente maior que os casos médio e o melhor. Note que o algoritmo heapsort não preserva a relativa ordenação de elementos iguais—isso torna o heapsort um algoritmo que produz o que se chama de ordenação instável. Todavia a ordem resultante de elementos iguais irá ser consistente através das diferentes plataformas quando se usa essas funções.
12.1 Ordenando objetos | ||
12.2 Ordenado vetores | ||
12.3 Selecionando os k menores ou maiores elementos | ||
12.4 Calculando o posto | ||
12.5 Exemplos | ||
12.6 Referências e Leituras Adicionais |
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
A seguinte função fornece uma alternativa simples à função padrão
de biblioteca qsort
. A seguinte função foi pensada para sistemas que não possuem a
qsort
, não como um substituto da mesma. A função qsort
deve ser usada sempre que possível, pois será mais rápida e pode fornecer
ordenação estável de elementos iguais. Documentação para qsort
está
disponível em GNU C Library Manual de Referência.
As funções descritas nessa seção são definidas no arquivo de cabeçalho ‘gsl_heapsort.h’.
Essa função ordena os count elementos do vetor estático array, cada um de tamanho size, em ordem ascendente usando a função de comparação compare. O tipo de dado usado na função de comparação é definido por,
int (*gsl_comparison_fn_t) (const void * a, const void * b)
Uma função de comparação deve retornar um inteiro negativo se o primeiro
argumento for menor que o segundo argumento, 0
se os dois argumentos
forem iguais e um inteiro positivo se o primeiro argumento for maior que
o segundo argumento.
Por exemplo, a seguinte função pode ser usada para ordenar números do tipo double em ordem numérica ascendente.
int compare_doubles (const double * a, const double * b) { if (*a > *b) return 1; else if (*a < *b) return -1; else return 0; }
A chamada de função apropriada para executar a ordenação é,
gsl_heapsort (array, count, sizeof(double), compare_doubles);
Note que diferentemente de qsort
o algoritmo heapsort não pode ser aplicado a uma
ordenação estável através de um apontador aritmético. O artifício de comparar ponteiros para
elementos iguais na função de comparação não trabalha para o algoritmo
heapsort. O algoritmo heapsort executa um rearranjo interno dos
dados que destrói sua ordem inicial.
Essa função indiretamente ordena os count elementos do vetor estático array, cada um de tamanho size, em ordem ascendente usando a função de comparação compare. A permutação resultante é armazenada em p, um vetor estático de comprimento n. Os elementos de p fornecem os índices dos elementos do vetor estático que deve ter sido armazenado naquela posição se o vetor estático tivesse sido ordenado nele próprio. O primeiro elemento de p fornece o índice do menor elemento armazenado no vetor estático array, e o último elemento de p fornece o índice do maior elemento em array. O vetor estático contido na variável array não é modificado.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
As funções seguintes irão ordenar os elementos vetor estático ou não,
tanto diretamente como indiretamente. Elas são definidas para todos os tipos de dado
tanto reais quanto inteiros usando as regras de sufixo normais. Por exemplo, as versões do tipo
float
das funções de vetor estático são gsl_sort_float
e
gsl_sort_float_index
. As correspondentes funções para vetor não estático são
gsl_sort_vector_float
e gsl_sort_vector_float_index
. Os
protótipos estão disponíveis nos arquivos de cabeçalho ‘gsl_sort_float.h’
‘gsl_sort_vector_float.h’. O conjunto completo de protótipos pode ser
incluído usando os arquivos de cabeçalho ‘gsl_sort.h’ e
‘gsl_sort_vector.h’.
Não existe funções para ordenar vetores estáticos ou não com elementos que pertencem ao campo dos númeors complexos, uma vez que a ordenação dos números complexos não é unicamente definida. Para ordenar um vetor complexo pelo módulo de seus elementos calcule um vetor real contendo os módulos dos elemntos complexos, e ordene esse vetor indiretamente. Os índices resultantes fornecem a ordenação apropriada do vetor complexo original.
Essa função ordena os n elementos do vetor estático data com salto stride em ordem numérica ascendente.
Essa função ordena os n elementos do vetor estático data1 com salto stride1 em ordem numérica ascendente, enquanto faz o mesmo rearranjo do vetor estático data2 com salto stride2, também de tamanho n.
Essa função ordena os elementos do vetor v em ordem numérica ascendente.
Essa função ordena os elementos do vetor v1 em ordem ascendente numérica, enquanto faz o mesmo rearranjo do vetor v2.
Essa função indiretamente ordena os n elementos do vetor estático data com salto stride em ordem ascendente, armazenando a permutação resultante em p. O vetor estático p deve ser alocado com um comprimento suficiente para armazenar os n elementos da permutação. Os elementos de p fornecem o índice do elemento do vetor estático que deveria ter sido armazenado naquela posição caso o vetor estático tivesse sido ordenado em si mesmo. O vetor estático data não é modificado.
Essa função ordena indiretamente os elementos do vetor v em ordem ascendente, armazenando a permutação resultante em p. Os elementos de p fornecem o índice do elemento do vetor que deveria ter sido armazenado naquela posição se o vetor tivesse sido ordenado em sí mesmo. O primeiro elemento de p fornece o índice do menor elemento em v, e o último elemento de p fornece o índice do maior elemento em v. O vetor v não é modificado.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
As funções descritas nessa seção selecionam o menor k ou o maior elemento de um conjunto de dados de tamanho N. As rotinas usam um algoritmo de inserção direta O(kN) que é ajustado a subconjuntos que são pequenos se comparados com o tamanho total do conjunto de dados. Por exemplo, as rotinas são úteis para selecionar os 10 maiores valores de entre um conjunto de um milhão de pontos de dados, mas esse mesmo algoritmo não é adequando para selecionar 100,000 valores nesse mesmo milhão de pontos. Se o subconjunto for uma parte significativa do conjunto total de dados pode ser mais rápido ordenar todos os elementos do conjunto de dados com um algoritmo O(N \logN) e obter os menores ou maiores valores.
Essa função copia os k menores elementos do vetor estático src, de tamanho n e salto stride, em ordem numérica ascendente gravando o resultado no vetor estático dest. O tamanho k do subconjunto deve ser menor que ou igual a n. Os dados armazenados em src não são modificados por essa operação.
Essa função copia os k maiores elementos do vetor estático src, de tamanho n e salto stride, em ordem numérica ascendente guardando o resultado no vetor estático dest. k deve ser menor que ou igual a n. Os dados armazenados em src não são modificados por essa operação.
Essas funções copiam os k menores ou maiores elementos do vetor v gravando o resultado no vetor estático dest. k deve ser menor ou igual ao comprimento do vetor v.
As funções seguintes encontram os índices dos k menores ou maiores elementos de um conjunto de dados,
Essa função armazena os índices dos k menores elementos do vetor estático src, de tamanho n e salto stride, no vetor estático p. Os índices são escolhidos de forma que os dados correspondentes sejam disponibilizados em ordem numérica ascendente. O valor k deve ser menor que ou igual a n. Os dados src não são modificados por essa operação.
Essa função armazena os índices dos k meiores elementos do vetor estático src, de tamanho n e salto stride, no vetor estático p. Os índices são escolhidos de forma que os dados correspondentes sejam disponibilizados em ordem numérica descendente. O valor k deve ser menor que ou igual a n. Os dados src não são modificados por essa operação.
Essas funções armazenam os índices dos k menores ou maiores elementos do vetor v no vetor estático p. k deve sr menor ou igual ao comprimento do vetor v.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
O posto de um elemento é sua ordem nos dados ordenados. O posto (33) é o inverso da permutação de índice, p. O posto pode ser calculado usando o seguinte algoritmo,
for (i = 0; i < p->size; i++) { size_t pi = p->data[i]; rank->data[pi] = i; }
O posto pode ser calculado diretamente a partir da função
gsl_permutation_inverse(rank,p)
.
A seguinte função irá mostrar o posto de cada elemento do vetor v,
void print_rank (gsl_vector * v) { size_t i; size_t n = v->size; gsl_permutation * perm = gsl_permutation_alloc(n); gsl_permutation * rank = gsl_permutation_alloc(n); gsl_sort_vector_index (perm, v); gsl_permutation_inverse (rank, perm); for (i = 0; i < n; i++) { double vi = gsl_vector_get(v, i); printf ("element = %d, value = %g, rank = %d\n", i, vi, rank->data[i]); } gsl_permutation_free (perm); gsl_permutation_free (rank); }
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
O seguinte exemplo mostra como usar a permutação p para mostrar os elementos do vetor v em ordem ascendente,
gsl_sort_vector_index (p, v); for (i = 0; i < v->size; i++) { double vpi = gsl_vector_get (v, p->data[i]); printf ("order = %d, value = %g\n", i, vpi); }
O próximo exemplo usa a função gsl_sort_smallest
para selecionar
os 5 menores números entre 100000 valores uniformemente aleatórios armazenados em um
vetor estático,
#include <gsl/gsl_rng.h> #include <gsl/gsl_sort_double.h> int main (void) { const gsl_rng_type * T; gsl_rng * r; size_t i, k = 5, N = 100000; double * x = malloc (N * sizeof(double)); double * small = malloc (k * sizeof(double)); gsl_rng_env_setup(); T = gsl_rng_default; r = gsl_rng_alloc (T); for (i = 0; i < N; i++) { x[i] = gsl_rng_uniform(r); } gsl_sort_smallest (small, k, x, 1, N); printf ("%d smallest values from %d\n", k, N); for (i = 0; i < k; i++) { printf ("%d: %.18f\n", i, small[i]); } free (x); free (small); gsl_rng_free (r); return 0; }
A saída mostra os 5 menores valores, em ordem ascendente,
$ ./a.out5 smallest values from 100000 0: 0.000003489200025797 1: 0.000008199829608202 2: 0.000008953968062997 3: 0.000010712770745158 4: 0.000033531803637743
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
O assunto de ordenar conjuntos é coberto extensivamente em Knuth Sorting and Searching,
O algoritmo Heapsort é descrito no seguinte livro,
[ << ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Esse documento foi gerado em 23 de Julho de 2013 usando texi2html 5.0.