C语言小知识——qsort函数


一、qsort函数声明

qsort是C中自带的快速排序函数,属于标准库<stdio.h>,在做算法题时会比较常用。
本文参考菜鸟教程

1.函数声明

void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))

2.参数含义

base: 是指向要排序的数组的第一个元素的指针,其实就是要排序的数组名;

nitems:表示待排序数组中的元素个数;

size: 指数组中每个元素所占的字节长度,可以用sizeof获得;

compar:用来比较两个元素的函数,返回值是int类型,输入的是两个可以指向任何数据类型(void*)的指针,但它们指向的值必须是常量(const)。

(可以看到,函数声明中的compar是一个函数指针的形式,因此可以直接将比较函数作为参数传入)

二、qsort函数用法

1.构造compare函数

int compar(const void *a, const void *b);

compar函数的两个输入a,b其实代表,指向待排序数组中的两个元素的指针。qsort的排序原则是由compar函数返回值决定的。

如果 compar 返回值小于 0(< 0),那么 a 所指向元素会被排在b所指向元素的前面;如果 compar 返回值等于 0(= 0),那么 a 所指向元素与 b 所指向元素的顺序不确定;如果 compar 返回值大于 0(> 0),那么 a 所指向元素会被排在 b 所指向元素的后面。


举个栗子:
// 待排序数组values
int values[] = { 88, 56, 100, 2, 25 };

//定义比较函数
int cmpfunc (const void * a, const void * b)
{
   return ( *(int*)a - *(int*)b );
}

(int*)a是对a进行类型转换,使它变为指向原数组中某个元素的指针;原数组元素都是int型,因此a应该变为(int *)。再在前面加*取值。

可以看到在上面这个cmpfunc函数中,当a指向的值大于b指向值时,会返回大于0的数,按照前面的规则,返回值>0,就把a排到b后面。
因此这个函数定义的排序规则,是将values中元素升序排序。

2.数组元素也是数组?

在对数组排序时,可能会出现数组中的元素也是一个数组,我们想要按照数组元素的第一个元素排序。这个在python中很容易实现:

nums = sorted(nums, key=lambda x: x[0])

通过使用lambda对key进行赋值。在C中,compar函数就相当于自定义了lambda,我们同样可以实现上面的效果。

定义compar函数为:

// 待排序数组
int *news[numsSize];
for(int i=0; i<numsSize; i++){
        news[i] = malloc(sizeof(int)*2);  // 长度为2的数组
}
// 定义比较函数
int compar(const void* a, const void* b)
{
    return (*(int**)a)[0] - (*(int**)b)[0];
}

我们定义待排序数组的每个元素都是一个数组,现在想要根据元素的第一维进行升序排序。
那么compar函数中,a的类型应该是(int **),这是因为此时待排序数组中的元素是(int *)类型(整型数组)的。 在前面加了*后,我们可以获取a指向的那个长度为2的数组。
由于我们想要根据元素的第一个值排序,所以用(*(int**)a)[0]取出第一个值进行比较。

可以看到,在对a进行数据类型转换时,只需要明确待排序数组元素的数据类型,再在此基础上加个*表示指针就行。

比如对字符数组排序,就是:

int compar(const void *a, const void *b)
{
	return *(char *)a - *(char *)b;
}	

其他一些可以参考博文


总结

qsort函数需要注意的是compar的构造;compar中对输入值的类型转换,以及输出值对排序规则的含义很重要!

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值