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

3

我在为 C 语言的 qsort 函数编写一个比较函数时遇到了些问题。以下是我目前的代码:

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

我知道如何使用比较函数,但我不明白如何引用我的结构体Individual中的整数值。以下是Individual的结构。
```html

这里列出了Individual的结构。

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

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


@kiner_shah 虽然链接的比较对于某些类型的浮点数比较是正确的,但它在这里不适用。 - Support Ukraine
1
@kiner_shah,您提供了一个与此问题无关的比较函数链接。 - Support Ukraine
2个回答

6
这部分
*(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是一个将被转换为整数的double类型。因此,0.1-0.0最终将返回0,这不是您想要的结果。

您可以查看@chqrlie在https://dev59.com/v7Dla4cB1Zd3GeqP2Aod#53466034中的答案以获取更多详细信息。

代码也可以更改如下:

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

2
假设您使用Individual结构的数组调用qsort,您应该将比较函数接收到的参数转换为指向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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接