📜  C语言中qsort()的比较器函数

📅  最后修改于: 2021-05-30 20:16:49             🧑  作者: Mango

标准C库提供了qsort(),可用于对数组进行排序。顾名思义,该函数使用QuickSort算法对给定数组进行排序。以下是qsort()的原型

void qsort (void* base, size_t num, size_t size, 
            int (*comparator)(const void*,const void*));

关于qsort()的关键是比较器函数比较器。比较器函数有两个参数,并包含逻辑来确定它们在排序输出中的相对顺序。这个想法是为了提供灵活性,以便qsort()可以用于任何类型(包括用户定义的类型),并且可以用于获取任何所需的顺序(递增,递减或任何其他顺序)。

比较器函数将两个指针作为参数(都类型转换为const void *),并通过返回(以稳定且可传递的方式)定义元素的顺序

int comparator(const void* p1, const void* p2);
Return value meaning
<0 The element pointed by p1 goes before the element pointed by p2
0  The element pointed by p1 is equivalent to the element pointed by p2
>0 The element pointed by p1 goes after the element pointed by p2

Source: http://www.cplusplus.com/reference/cstdlib/qsort/

例如,假设有一个学生数组,其中关注的是学生类型。

struct Student
{
    int age, marks;
    char name[20];
};

可以说,我们需要根据分数以升序对学生进行排序。比较器函数如下所示:

int comparator(const void *p, const void *q) 
{
    int l = ((struct Student *)p)->marks;
    int r = ((struct Student *)q)->marks; 
    return (l - r);
}

有关qsort()的更多示例用法,请参见以下文章。
给定一系列单词,将所有字谜一起打印
箱子堆放问题
最接近的点对

以下是一个有趣的问题,可以借助qsort()和比较器函数轻松解决。
给定整数数组,请按以下顺序对其进行排序:奇数首先出现,偶数随后出现。奇数应按降序排序,偶数应按升序排序。

一种简单的方法是首先修改输入数组,以便分离偶数和奇数,然后分别对两个部分(奇数和偶数)应用某种排序算法。

但是,存在一种有趣的方法,对“快速排序”的比较器函数进行了一些修改。想法是编写一个比较器函数,该函数将两个地址p和q作为参数。令l和r为p和q所指向的数字。该函数使用以下逻辑:
1)如果(l和r)都为奇数,则将两者中的较大者放在首位。
2)如果两个(l和r)均为偶数,则将两个中较小的一个放在第一位。
3)如果其中一个是偶数而另一个是奇数,则将奇数放在第一位。

以下是上述方法的C实现。

#include 
#include 
  
// This function is used in qsort to decide the relative order
// of elements at addresses p and q.
int comparator(const void *p, const void *q)
{
    // Get the values at given addresses
    int l = *(const int *)p;
    int r = *(const int *)q;
  
    // both odd, put the greater of two first.
    if ((l&1) && (r&1))
        return (r-l);
  
    // both even, put the smaller of two first
    if ( !(l&1) && !(r&1) )
        return (l-r);
  
    // l is even, put r first
    if (!(l&1))
        return 1;
  
    // l is odd, put l first
    return -1;
}
  
// A utility function to print an array
void printArr(int arr[], int n)
{
    int i;
    for (i = 0; i < n; ++i)
        printf("%d ", arr[i]);
}
  
// Driver program to test above function
int main()
{
    int arr[] = {1, 6, 5, 2, 3, 9, 4, 7, 8};
  
    int size = sizeof(arr) / sizeof(arr[0]);
    qsort((void*)arr, size, sizeof(arr[0]), comparator);
  
    printf("Output array is\n");
    printArr(arr, size);
  
    return 0;
}

输出:

Output array is
9 7 5 3 1 2 4 6 8

锻炼:
给定整数数组,请以其他方式对其进行排序。备用方式表示将偶数索引的元素分别排序,将奇数索引的元素分别排序。

想要从精选的最佳视频中学习和练习问题,请查看《基础知识到高级C的C基础课程》。