qsort中的compare函数如何工作?

时间:2014-12-04 00:23:40

标签: c quicksort

我在网上找到了这个示例代码,它解释了qsort函数的工作原理。我无法理解比较函数返回的内容。

#include "stdlib.h"

int values[] = { 88, 56, 100, 2, 25 };

int cmpfunc (const void * a, const void * b) //what is it returning?
{
   return ( *(int*)a - *(int*)b ); //What is a and b?
}


int main(int argc, _TCHAR* argv[])
{

   int n;

   printf("Before sorting the list is: \n");
   for( n = 0 ; n < 5; n++ ) {
      printf("%d ", values[n]);
   }

   qsort(values, 5, sizeof(int), cmpfunc);

   printf("\nAfter sorting the list is: \n");
   for( n = 0 ; n < 5; n++ ) {
      printf("%d ", values[n]);
   }
    return 0;
}

6 个答案:

答案 0 :(得分:8)

int cmpfunc (const void * a, const void * b) //what is it returning?
{
   return ( *(int*)a - *(int*)b ); //What is a and b?
}

相当于:

int cmpfunc (const void * a, const void * b) //what is it returning?
{
   // qsort() passes in `void*` types because it can't know the actual types being sorted
   // convert those pointers to pointers to int and deref them to get the actual int values

   int val1 = *(int*)a;
   int val2 = *(int*)b;

   // qsort() expects the comparison function to return:
   // 
   //    a negative result if val1 < val2
   //    0 if val1 == val2
   //    a positive result if val1 > val2

   return ( val1 - val2 ); 
}

答案 1 :(得分:3)

a的文档中明确说明了bqsort的内容:这些是指向必须比较的数组元素的指针。

在这种情况下,比较函数知道数组元素的类型为int。因此,它将void *指针转换为int *类型,并通过从第一个值中减去第二个来执行指向int值的三态比较。

它适用于您的值集,但一般情况下使用减法进行三态比较是一种糟糕的编程习惯,因为它容易溢出。此外,示例代码中的函数不必要地抛弃了指向值的常量。

更好的选择是

int cmpfunc(const void *a, const void *b)
{
   const int *A = a, *B = b;
   return (*A > *B) - (*A < *B);
}

答案 2 :(得分:2)

每当排序算法需要找出两个元素中的哪一个应该放在另一个之前时,它将调用比较函数并将指针传递给这两个元素。由于您要对int值进行排序,因此指针实际上是指向int的指针,但签名必须采用void*,以便它可以与任何数据类型一起使用。因此,为了获得实际元素值,必须将a强制转换为int*,然后将其解除引用 - 因此,*(int*)a。如果a放在b之前,则函数必须返回负值;如果要b放置a,则返回正值;如果不放置b则返回0 39;首先放置的东西(通常是元素相等时的情况)。在这种特殊情况下,由于我们正在处理数字,因此如果我们希望将最大数字放在第一位,只需从a的值中减去{{1}}的值即可。

答案 3 :(得分:2)

来自http://en.cppreference.com/w/cpp/algorithm/qsort

如果第一个参数小于第二个参数,cmp函数返回一个负整数值, 如果第一个参数大于第二个参数,则为正整数值;如果参数相等,则为零。

该函数使用void指针,因此qsort函数可以与任何数据类型一起使用。但是在cmp函数内部,您必须显式地将指针强制转换为实际数据类型。

答案 4 :(得分:1)

ab被比较为整数 - 它们必须以void *传递,但在最终被推崇之前被投射到int *。至于返回值,它将是正数,负数或零,所有这些都将在排序函数中考虑。

答案 5 :(得分:0)

qsort会给它需要与cmpfunc进行比较的每一对,并使用它的返回值来查看哪一个更大,然后相应地对数组进行排序。

基本上,如果compare函数返回肯定结果,则意味着第一个参数大于第二个参数。同样,如果它返回负数,那么第二个参数更大。

在示例中,我们要对整数进行排序。因此,当我们比较给定数组的两个元素时,我们需要决定哪一个更大。为了比较这些,一个简单的减法操作就足够了,因为当a更大时结果为正,如果a和b相等则为0,如果b更大则为负。