按其内部属性的值对结构进行排序

huangapple go评论75阅读模式
英文:

Sort Structs by the value of an attribute in it

问题

我的问题是,当我尝试对一个名为ann的结构体列表进行排序时,如下所示:

typedef struct ann {
int inputs; /* 输入神经元数量 /
int hidden_layers; /
隐藏层数量 /
int hidden; /
隐藏神经元数量 /
int outputs; /
输出神经元数量 /
int weights; /
总权重(染色体)数量 /
int neurons; /
总神经元数量 */
double weight; / 权重(基因型) */
double output; / 输出 /
double fitness; /
网络的总适应度 */
double delta;
actfun activation_hidden; /
隐藏层激活函数 /
actfun activation_output; /
输出层激活函数 */
} 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);

/* 为权重、输出和delta分配额外空间。 */
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;

/* 设置指针。 */
ret->weight = (double*)((char*)ret + sizeof(ann));
ret->output = ret->weight + ret->weights;
ret->delta = ret->output + ret->neurons;

return ret;

}


我明白这可能是微不足道的,但我已经尝试了很多方法,似乎无法解决它,而且我已经花了很多小时尝试修复它,任何帮助都将是伟大的,提前感谢所有人。
英文:

i am trying to sort a struct by the value of a double attrib in it, kind of like this

#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);
}

My issue is when i try to sort a list of struct named ann as shown below

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 does not alter the order

here is my actual code

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;
}

Also here is the create() function

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;
}

I understand this may be trivial, but i have tried to do this in so many ways and i cant seem to figure it out, and i have spend many many hours trying to fix it already, and any help will be great, thanks to all in advance.

答案1

得分: 3

变量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);
}

请注意返回语句。否则,将double类型的差异转换为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
英文:

The variable population has the type ann **. Each element of the allocated array has the type ann *.So the function qsort should be called like

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

Within the comparison function you should write

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

Pay attention to the return statement. Otherwise the difference of doubles in the return statement converted to the type int can produce an unexpected result.

return pa-&gt;fitness - pb-&gt;fitness;

Also this memory allocation

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

does not make sense. Either allocate a memory of the size equal to sizeof( ann ) or use another structure that encloses the structure ann.

Here is a demonstrative program.

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

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-&gt;x &lt; left-&gt;x ) - (  left-&gt;x &lt; right-&gt;x );
}

int main(void) 
{
	size_t n = 10;
	struct A **a = malloc( n * sizeof( struct A * ) );
	
	for ( size_t i = 0; i &lt; n; i++ )
	{
		a[i] = malloc( sizeof( struct A ) );
		a[i]-&gt;x = ( double )( n - i ) / n;
	}
	
	for ( size_t i = 0; i &lt; n; i++ ) printf( &quot;%.1f &quot;, a[i]-&gt;x );
	putchar( &#39;\n&#39; );

	qsort( a, n, sizeof( struct A * ), cmp );
	
	for ( size_t i = 0; i &lt; n; i++ ) printf( &quot;%.1f &quot;, a[i]-&gt;x );
	putchar( &#39;\n&#39; );

	for ( size_t i = 0; i &lt; n; i++ ) free( a[i] );
	free( a );
	
	return 0;
}

Its output is

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

huangapple
  • 本文由 发表于 2020年1月6日 21:02:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/59612610.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定