1

我一直在寻找一种在 C 中对数组子集进行排序的方法,而无需将元素移动到临时数组并将它们复制回来。我可能对 qsort 有不好的理解,但我认为下面的代码应该可以工作:

qsort(&my_struct_arr[1],3,sizeof(my_struct),my_struct_cmp);
//my_struct_arr is a 4 element array, where i want to sort from position 1 to 3
int my_struct_cmp(const void *a, const void *b)
{
    my_struct A=*(my_struct*)a, B=*(my_struct*)b;
    if(A.x-B.x < 0.01) return A.y-B.y;
    return A.x-B.x;
}
typedef struct foo
{
    float x, y;
} my_struct;

问题是,它不起作用。

更新 1: 好的,我知道我对这个问题并不完全清楚。我将数组从位置 1 初始化到 3,所以我有一个包含如下元素的数组:

{ { ValueFromPreviousIteration.x,ValueFromPreviousIteration.y }, {x1,y1}, {x2,y2}, {x3,y3} }

我的问题是,像上面那样调用的 qsort 将对整个数组进行排序,而我只想对它的最后 3 个元素进行排序。

4

4 回答 4

1

您的比较功能不稳定。它可以根据传递结构的顺序返回不同的结果。

考虑以下结构值:

my_struct m = { -3.021, 30 };
my_struct n = { 3.010, 0 };    

int main(void)
{
    int comp1 = my_struct_cmp( &m, &n);
    int comp2 = my_struct_cmp( &n, &m);

    printf( "%d %d\n", comp1, comp2);

    return 0;
}

第一个比较表明m > n,而第二个表明n > m。这种行为让人迷惑qsort()

于 2012-11-30T09:32:11.223 回答
0

int my_struct_cmp返回整数。

而你又回来了float。它将自动转换为 int,并且可能0.

这就是为什么它不起作用。

于 2012-11-30T09:18:18.560 回答
0

是否if(A.x-B.x < 0.01)正确?你可能想要if(A.x-B.x < 0.0). 使用0.0代替 0.01

于 2012-11-30T09:21:59.823 回答
0

我认为您需要将比较功能修改为

int my_struct_cmp(const void* a, const void* b)
{
    const my_struct A = *(my_struct*)a, B = *(my_struct*)b;
    return fabs(A.x - B.x) >= 0.01 ? (A.x > B.x) - (A.x < B.x) : (A.y > B.y) - (A.y < B.y);
}

或(不那么便携)

int my_struct_cmp(const void* a, const void* b)
{
    const my_struct A = *(my_struct*)a, B = *(my_struct*)b;
    return fabs(A.x - B.x) >= 0.01 ? copysign(1, A.x - B.x) : copysign(1, A.y - B.y);
}

否则,存在许多特定于平台的解决方案,用于在不执行比较的情况下确定浮点数的符号,这实际上并非易事。

这应该更快一点:

int my_struct_cmp(const void* a, const void* b)
{
    const my_struct *A = (my_struct*)a, *B = (my_struct*)b;
    return fabs(A->x - B->x) >= 0.01 ? (A->x > B->x) - (A->x < B->x) : (A->y > B->y) - (A->y < B->y);
}
于 2012-11-30T09:50:00.237 回答