为 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);
}
我在用 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);
}