为什么按降序排列的 qsort int 数组不正确?

Why qsort int array in descending order is incorrect?

我尝试编写用于对 int 数组进行 qsorting 的比较函数。它给出了升序的正确结果。但是对于降序是不正确的。为什么?什么是正确的 compare int 函数?

int compare(const void *a, const void *b){
    int x = *(int*)a;
    int y = *(int*)b;
    return (x > y) - (x < y);
}

int reverse(const void *a, const void *b){
    return -compare(a, b);
}

int main(){
    int x[] = {500, 456, 18, 13, 3, 89, 800, 6874};
    qsort(x, sizeof(x[0]), sizeof(x)/sizeof(x[0]), reverse);
    for (int i=0; i < sizeof(x)/sizeof(x[0]); i++){
    printf("%d\n", x[i]);

    return 0;
}

我希望打印的整数降序排列,从最大的 6874 到最小的 3。 但我却收到了:

800 6874 500 456 18 13 3个 89

您已经交换了 qsort 的第二个和第三个参数 -- 它应该是

qsort(x, sizeof(x)/sizeof(x[0]), sizeof(x[0]), reverse);

你调用它的方式,因为你的数组恰好是 8 个元素,而 sizeof(int) 在你的机器上恰好是 4,它是根据每对的第一个整数对整数对进行排序。

在处理其他方面之前,你已经将第二个和第三个参数切换为qsort(3)第一个是数组指针,第二个是元素个数,第三个是大小,第四个是比较函数指针。要做好 qsort(3) 你首先需要把参数放在正确的顺序 :).

嗯,compare()函数必须return< 0(不是-1)如果a小于b> 0(而不是 +1) 如果 a 大于 b 并且如果 ab 相等则为零。你的公式是正确的,但有点过于复杂的表达,因为可以通过减去两个参数来实现。如果你检查 strcpy(3) 的许多实现做了什么 return (嗯,不是全部,但很多)是两个字符串不同位置的字符代码之间的差异,这足以进行有效的实现。

顺便说一句,你知道 void * 是一个与任何其他指针类型兼容的指针,因此编写比较函数的最佳方法之一(基于对整数的引用而不是它们的值) 就是这样写:

int compare(int *a, int *b) 
{
    return *a - *b;
}

int reverse_compare(int *a, int *b) 
{
    return -compare(a, b);
}

(你会在 qsort(3) 的调用中得到一个可忽略的警告)或者更简单的

int reverse_compare(int *a, int *b) 
{
    return compare(b, a);
}

并直接传递给qsort(3)。事实上,反向比较只需要两个指针,并且可以通过将其编写为完全通用:

int reverse_compare(const void *a, const void *b)
{
    return compare(b, a);
}

pru.c

如果检查以下示例,您会看到 reverse 是传递给 qsort 的例程(没有警告,因为参数匹配,并且 [=30 的正文中没有警告=] 在对 compare_int 的调用中将它们转换为 void * 时。)

#include <stdlib.h>
#include <stdio.h>

int compare_int(const int *a, const int *b)
{
    return (*a > *b) - (*b > *a);
}

int reverse(const void *a, const void *b)
{
    return compare_int(b, a);
}

int main()
{
    int x[] = {500, 456, 18, 13, 3, 89, 800,
        6874};
    qsort(x,
        sizeof(x)/sizeof(x[0]),
        sizeof(x[0]),
        reverse);
    for (int i=0; i <
            sizeof(x)/sizeof(x[0]); i++) {
        printf("%d\n", x[i]);
    }

    return 0;
}