qsort的cmp函数理解
qsort使用
近期频繁使用qsort函数,但是对于cmp函数却一直不太熟悉,现用现查。故写一篇小笔记记录一下。
函数原型:
void qsort(void *base,size_t NumEle,size_t SizeEle,int (cmp*)(const void *a,const void *b))
值得注意的是cmp这个函数指针,返回值类型必须是int,参数是两个const void *
,在写cmp函数时,可以选择在函数体内,再将a,b强转为所需要的类型,而因为void *
的特殊性,也可以在写函数签名是用const T*
代替。
cmp函数
以一个int数组为例,现在要将这个数组按照元素大小,升序排列。cmp函数与参数a,b对于qsort的影响是
if a>b return positive
if a=b return 0
if a<b return negative
按照这个要求设计的return
就会使得按照升序排序,注意是按照这个要求去设计所需要的返回值!只要能保住a,b在你设计的规则下,产生这样的返回值即可。
而这三个条件刚好与a-b
等价:
a>b return positive ~ a-b
a=b return 0 ~ a-b
a<b return negative ~ a-b
因而cmp
函数可以写为:
int cmp(const void *a,const void *b){
return *(int*)a-*(int*)b;/*按照升序排序*/
}
那么按照这个思想,同样可以写出字符串按字典序,因为strcmp
函数的返回值,正与我们所要求的升序设计一致。因而cmp函数可以写为:
int cmp(const void *a,const void *b){
return (char*)a-(char*)b;/*按照升序排序*/
}
对于结构体的排序也是如此,只是要注意类型的转化。多级排序就设计一个if/else即可,例如:
struct pair{
int x;
int y;
}P[100];
/*
当x不相等时,按照x升序排序,否则就按y降序排列
*/
int cmp(const void *a,const void *b){
struct pair* p_a=(struct pair*)a;
struct pair* p_b=(struct pair*)b;
if(p_a->x==p_b->x){
return p_a->x - p_b->x;
}else{
reyurn p_b->y - p_a->y;
}
}
qsort(P,100,sizeof(P[0]),cmp);
总结
因此,要弄清楚cmp的意义,关键在于如何排序是有规定的,我们要根据这个规定去设计cmp函数的返回值。
按照升序排序的要求:对于任意的元素a,b(假定比较运算符有意义)
if a>b return positive
if a=b return 0
if a<b return negative