【问题标题】:Sort Structs by the value of an attribute in it按其中的属性值对结构进行排序
【发布时间】:2020-04-24 00:38:39
【问题描述】:

我正在尝试根据其中的双属性值对结构进行排序,有点像这样

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

我知道这可能是微不足道的,但我尝试了很多方法,但我似乎无法弄清楚,我已经花了很多时间试图修复它,任何帮助都会很棒,提前感谢大家。

【问题讨论】:

  • 看起来你有一个指向结构的指针数组,但你调用 qsort 就像它是一个结构数组?
  • 那么如何调用 qsort 之类的指向 struct 的指针? @肖恩
  • 也许我已经是代码盲了,但我看不到您实际设置 fitness 成员值的任何地方 - 您稍后会在比较函数中使用该值。
  • 暂时填充随机数
  • 但是“未初始化”并不是真正的“随机”——所有值都可以设置为相同的“任意”数字,因此不会发生排序。

标签: c sorting memory-management struct qsort


【解决方案1】:

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

注意return语句。否则将 return 语句中的双精度差转换为 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

【讨论】:

  • 什么是struct A,struct A可以写成ann吗?
  • @SimSadrowpsX 使用你想要的任何结构。我演示了一种方法,如何通过结构的 double 类型的某些数据成员来处理指向结构的指针数组。
  • 其中的属性是什么?
  • @SimSadrowpsX 我不明白你的问题。什么不清楚?
  • 对不起,我太笨了,谢谢你会试试这个,但我的问题是我有一个名为 create() 的创建函数,这会改变a[i] = malloc( sizeof( struct A ) );
猜你喜欢
  • 2011-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-12
  • 2023-04-03
  • 2015-06-13
  • 2021-07-20
  • 1970-01-01
相关资源
最近更新 更多