c语言 - 为什么 qsort 不起作用,同时对结构数组进行排序



我有一个这样的结构数组

typedef union value_
{
double d;
int i;
} value;
typedef struct number_
{
char type;
value val;
}number;

类型可以是'i''d',具体取决于存储在并集字段中的整数或双值。阵列如下所示:

Integer value: -3
Double value: 4.84
Integer value: -4
Double value: 1.65
Integer value: 1
Double value: 2.54
Integer value: 2
Double value: -0.09

最重要的是,整数和二重是一个接一个的。我需要按照下一种方式使用qsort对这个数组进行排序:整数应该从低到高排序,反之亦然。我使用以下功能进行比较:

int compare(const void *A, const void *B){
number *a = (number*)A;
number *b = (number*)B;

if (a->type == b->type) {
if (a->type =='i') {
return a->val.i - b->val.i;
} else {
if (a->val.d > b->val.d) return -1;
if (a->val.d < b->val.d) return 1;
else return 0;
}
} else {
return 0;
}
}

假设,如果并集中的值具有不同的类型,则它在不进行比较的情况下返回0,因此应该保存诸如int、double、int、double。但结果如下:

Integer value: -1
Integer value: -5
Double value: 0.20
Integer value: 2
Double value: -0.04
Double value: -2.69
Integer value: 4
Integer value: 5
Double value: 2.04
Integer value: 3

如果在这种情况下它应该返回0,为什么它会用整数改变双精度?

如果您需要保留intdouble类型的原始列表的"互锁模式",但对每组intdouble值进行排序,则不能在完整列表中按原样使用标准qsort函数。

但是,您可以将intdouble条目分离到新列表中,分别对它们进行排序,然后将两个排序的列表合并回原始列表,根据原始列表中条目的类型,从相关排序列表中提取intdouble条目。

这里有一个可能的实现(使用代码中的compare函数保持不变——尽管如果您制作两个特定于类型的比较函数用于分离的列表,则对于大列表会获得更好的性能(:

void printlist(number* list, size_t n)
{
for (size_t i = 0; i < n; ++i) {
if (list[i].type == 'i') printf("%d ", list[i].val.i);
else printf("%lf ", list[i].val.d);
}
printf("n");
}
int main()
{
number list[] = {
{ 'i', { .i = -3} },   { 'd', { .d = 1.65} },
{ 'i', { .i = -4} },   { 'd', { .d = 4.85} },
{ 'i', { .i =  1} },   { 'd', { .d = -.09} },
{ 'i', { .i =  2} },   { 'd', { .d = 2.54} },
};
size_t Tcount = sizeof(list) / sizeof(*list), Icount = 0, Dcount = 0; // Counts for total, ints and doubles
for (size_t i = 0; i < Tcount; ++i) {
if (list[i].type == 'i') ++Icount;
else ++Dcount;
}
// Display original list ...
printlist(list, Tcount);
number* Ilist = malloc(sizeof(number) * Icount);
number* Dlist = malloc(sizeof(number) * Dcount);
size_t Iindex = 0, Dindex = 0;
// Separate lists ...
for (size_t i = 0; i < Tcount; ++i) {
if (list[i].type == 'i') Ilist[Iindex++] = list[i];
else Dlist[Dindex++] = list[i];
}
// Sort each list separately ...
qsort(Ilist, Icount, sizeof(number), compare);
qsort(Dlist, Dcount, sizeof(number), compare);
// Merge sorted lists ...
Iindex = 0, Dindex = 0;
for (size_t i = 0; i < Tcount; ++i) {
if (list[i].type == 'i') list[i] = Ilist[Iindex++];
else list[i] = Dlist[Dindex++];
}
// Display sorted list ...
printlist(list, 8);
// Clean up ...
free(Ilist);
free(Dlist);
return 0;
}

最新更新