Сортировать по значению атрибута - PullRequest
0 голосов
/ 06 января 2020

Я пытаюсь отсортировать структуру по значению двойного атрибута, вроде этого

#include <stdio.h>
#include <stdlib.h>

double arr[] = {1.023, 1.22, 1.56, 2, 5, 3.331};

int cmp(const void *x, const void *y)
{
  double xx = *(double*)x, yy = *(double*)y;
  if (xx < yy) return -1;
  if (xx > yy) return  1;
  return 0;
}

int main() {
    qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(arr[0]), cmp);
}

Моя проблема возникает, когда я пытаюсь отсортировать список структуры с именем ann, как показано ниже

typedef struct ann {
    int inputs;                 /* Number of input neurones      */
    int hidden_layers;          /* Number of hidden layers       */
    int hidden;                 /* Number of hidden neurones     */
    int outputs;                /* Number of output neurons.     */
    int weights;                /* Total nof weigths(chromosomes)*/
    int neurons;                /* Total Number of neurones      */
    double *weight;             /* The weights(genotype)         */
    double *output;             /* Output                        */
    double fitness;              /* Total fitness of the network    */
    double *delta;
    actfun activation_hidden;   /* Hidden layer activation func  */
    actfun activation_output;   /* Output layer activation func  */
} ann;

qsort не меняет порядок

вот мой фактический код

ann **population = malloc ( population_size * sizeof(ann*));

    for( i = 0; i < population_size; i++ ){
        population[i] = create( trainset->num_inputs, 1 , hidden, trainset->num_outputs);
    }

qsort( population, population_size, sizeof(ann), compareAnn);

int compareAnn(const void* a, const void* b)
{
  const ann* pa = (const ann*)a;
  const ann* pb = (const ann*)b;
  return pa->fitness - pb->fitness;
}

Также здесь есть функция create ()

ann *create   ( int inputs, int hidden_layers, int hidden, int outputs ) {

    const int hidden_weights = hidden_layers ? (inputs+1) * hidden + (hidden_layers-1) * (hidden+1) * hidden : 0;
    const int output_weights = (hidden_layers ? (hidden+1) : (inputs+1)) * outputs;
    const int total_weights = (hidden_weights + output_weights);

    const int total_neurons = (inputs + hidden * hidden_layers + outputs);

    /* Allocate extra size for weights, outputs, and deltas. */
    const int size = sizeof(ann) + sizeof(double) * (total_weights + total_neurons + (total_neurons - inputs));
    ann *ret = malloc(size);
    if (!ret) return 0;

    ret->inputs = inputs;
    ret->hidden_layers = hidden_layers;
    ret->hidden = hidden;
    ret->outputs = outputs;

    ret->weights = total_weights;
    ret->neurons = total_neurons;

    /* Set pointers. */
    ret->weight = (double*)((char*)ret + sizeof(ann));
    ret->output = ret->weight + ret->weights;
    ret->delta = ret->output + ret->neurons;

    return ret;
}

Я понимаю, что это может быть тривиально, но я пытался сделать это многими способами, и я, кажется, не могу понять это, и я потратил много часов, пытаясь это исправить, и любая помощь будет отличной, спасибо всем заранее.

1 Ответ

3 голосов
/ 06 января 2020

Переменная population имеет тип ann **. Каждый элемент выделенного массива имеет тип ann *. Так что функция qsort должна вызываться как

qsort( population, population_size, sizeof( ann * ), compareAnn );

В функции сравнения вы должны написать

int compareAnn(const void* a, const void* b)
{
  const ann* pa = *( const ann ** )a;
  const ann* pb = *( const ann ** )b;
  return ( pb->fitness < pa->fitness ) - ( pa->fitness - pb->fitness );
}

Обратите внимание к заявлению о возврате. В противном случае разница двойников в операторе возврата, преобразованном в тип int, может привести к неожиданному результату.

return pa->fitness - pb->fitness;

Кроме того, это распределение памяти

const int size = sizeof(ann) + sizeof(double) * (total_weights + total_neurons + (total_neurons - inputs));
ann *ret = malloc(size);

не имеет смысла. Либо выделите память размером, равным sizeof( ann ), либо используйте другую структуру, которая включает в себя структуру ann.

Вот демонстрационная программа.

#include <stdio.h>
#include <stdlib.h>

struct A
{
    double x;
};

int cmp( const void *a, const void *b )
{
    const struct A *left  = *( const struct A ** )a;
    const struct A *right = *( const struct A ** )b;

    return ( right->x < left->x ) - (  left->x < right->x );
}

int main(void) 
{
    size_t n = 10;
    struct A **a = malloc( n * sizeof( struct A * ) );

    for ( size_t i = 0; i < n; i++ )
    {
        a[i] = malloc( sizeof( struct A ) );
        a[i]->x = ( double )( n - i ) / n;
    }

    for ( size_t i = 0; i < n; i++ ) printf( "%.1f ", a[i]->x );
    putchar( '\n' );

    qsort( a, n, sizeof( struct A * ), cmp );

    for ( size_t i = 0; i < n; i++ ) printf( "%.1f ", a[i]->x );
    putchar( '\n' );

    for ( size_t i = 0; i < n; i++ ) free( a[i] );
    free( a );

    return 0;
}

Ее вывод

1.0 0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1 
0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
...