在数组的子集上调用qsort

时间:2012-11-30 09:14:39

标签: c struct qsort

我一直在寻找一种在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 个答案:

答案 0 :(得分: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()

答案 1 :(得分:0)

int my_struct_cmp返回int。

你要回归float。它将自动转换为int,可能是0

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

答案 2 :(得分:0)

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

答案 3 :(得分: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);
}