为qsort的结构编写比较函数吗?

时间:2018-11-25 06:18:29

标签: c genetic-algorithm qsort

我在用C为qsort函数编写比较函数时遇到麻烦。这是我目前拥有的:

int cmpfunc(const void *a, const void *b) {
    return (*(Individual*)a->fitness - *(Individual*)b->fitness);
}

我知道比较函数的工作原理,但不了解如何在我的名为Individual的结构中引用整数值。这是个人的结构。

typedef struct {
    PPM_IMAGE image;
    double fitness;
} Individual;

我想比较结构中的适应度值。

2 个答案:

答案 0 :(得分:5)

这部分

*(Individual*)a->fitness

是错误的。您尝试使用fitness访问->,但同时使用*取消引用指针。你不能两者都做!

这是两种解决方法。

解决方案A:使用*解引用并使用fitness访问.

(*(Individual*)a).fitness

解决方案B:使用fitness访问->

((Individual*)a)->fitness

这两种解决方案都需要将void*转换为Individual*

对于变量b

同样适用

如果您是C语言的初学者,我建议您避免在发生多种情况的情况下使用紧凑型语句。而是将压缩语句拆分为多个单独的语句。这将使代码更易于理解和调试。喜欢:

int cmpfunc (const void * a, const void * b){
    Individual* pA = a;
    Individual* pB = b;
    double fitnessA = pA->fitness;
    double fitnessB = pB->fitness;
    return fitnessA - fitnessB;
}

您无需担心性能。编译器会将代码优化为与单语句代码一样高效。

那是-由@chqrlie发现-请注意比较代码是错误的!

该函数返回一个整数,但是fitnessA - fitnessB是将被转换为整数的双精度型。因此0.1 - 0.0最终将返回0-这不是您想要的。

您可以从@chqrlie看到此答案https://stackoverflow.com/a/53466034/4386427,以获取更多详细信息。

代码也可以像这样更改:

int cmpfunc (const void * a, const void * b){
    Individual* pA = a;
    Individual* pB = b;
    double fitnessA = pA->fitness;
    double fitnessB = pB->fitness;
    if (fitnessA > fitnessB) return 1;
    if (fitnessA < fitnessB) return -1;
    return 0;
}

答案 1 :(得分:2)

假设您使用qsort结构数组调用Individual,则应将compare函数收到的参数强制转换为Individual结构的指针,最好是const Individual *以避免警告。

然后可以比较fitness个成员并返回订购值。请注意,您不能只返回值的差,因为它们可能不是整数,并且差甚至可能溢出类型int的范围。

这是执行此操作的经典方法:

int cmpfunc(const void *a, const void *b) {
    const Individual *aa = a;
    const Individual *bb = b;
    /* return -1, 0 or 1 depending on the comparison results */
    return (aa->fitness > bb->fitness) - (aa->fitness < bb->fitness);
}