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

Writing a compare function for a structure for qsort?

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

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

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

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

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

这部分

*(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 所发现的 - 注意比较代码是错误的!

函数 returns 是一个整数,但 fitnessA - fitnessB 是一个将被转换为整数的双精度数。所以 0.1 - 0.0 最终会返回 0 - 这不是你想要的。

您可以从@chqrlie 看到这个答案 了解更多详情。

代码也可以改成:

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

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

然后您可以比较 fitness 个成员和 return 个排序值。请注意,您不能只 return 值的差异,因为这些值可能不是整数,并且差异甚至可能溢出 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);
}