C语言qsort排序

1 qsort原理介绍

函数原型:

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

base – 指向要排序的数组的第一个元素的指针。
nitems – 由 base 指向的数组中元素的个数。
size – 数组中每个元素的大小,以字节为单位。
compar – 用来比较两个元素的函数。

注意cmp这个函数指针,返回值类型必须是int,参数是两个const void *,因此在写cmp函数时,可以选择在函数体内,再将a,b强转为所需要的类型;

我们以一个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;/*按照升序排序*/  //降序就是 *(int*)b-*(int*)a;
}

strcmp函数,也就是把字符串str1和str2从首字符开始逐个字符的进行比较,直到某个字符不相同或者其中一个字符串比较完毕才停止比较。

int strcmp(char *str1,char * str2);

那么可以等价如下:

a>b return positive ~ a-b strcmp(a, b)//若字符串a大于字符串b,返回结果大于零;
a=b return 0        ~ a-b strcmp(a, b)//若字符串a等于字符串b,返回结果等于零;
a<b return negative ~ a-b strcmp(a, b)//若字符串a小于字符串b,返回结果小于零;

strcmp函数返回值正与我们所要求的升序设计一致,所以字符串操作cmp函数可写为:

int cmp(const void *a, const void *b) {
	return strcmp((char * )a, (char *)b);
} 

2 qsort使用举例

2.1 一维数组排序

// 一维排序
int cmp1(const void *a, const void *b)
{
    int *x = (int *)a;
    int *y = (int *)b;
    return (*x) - (*y); // 升序,降序改为 (*y) - (*x)
}
// 一维排序
int arr[] = {9, 13, 12, -1, -1, 2, 8};
int arrLen = sizeof(arr) /sizeof(arr[0]);
qsort(arr, arrLen, sizeof(arr[0]), cmp1);
//排序结果arr1: -1 -1 2 8 9 12 13

2.2 二维数组排序

// 二维排序
int cmp2(const void *a, const void *b)
{
    int *x = (int *)a;
    int *y = (int *)b;
    return x[0] - y[0]; // 按照特性一升序,  按照特性二升序为 x[1] - y[1]
}
// 二维排序
int arr2[3][2] = {{7,6},{2,4},{1,2}}; // 三组数据:每组数据两个特性
qsort(arr2, 3, sizeof(arr2[0]), cmp2);
/*排序结果
arr2
1 2
2 4
7 6
*/

2.3 二维数组排序升级

// 二维排序
int cmp3(const void *a, const void *b)
{
    int *x = (int *)a;
    int *y = (int *)b;
    if (x[0] == y[0]) { // 特性一相同,按照特性二进行升序
        return x[1] - y[1];
    }
    return x[0] - y[0]; // 按照特性一升序
}
// 二维排序
int arr3[3][2] = {{1,6},{2,4},{1,2}}; // 三组数据:每组数据两个特性
qsort(arr3, 3, sizeof(arr3[0]), cmp3);
/*排序结果
arr3
1 2
1 6
2 4
*/

2.4 二维数组指针排序

//二维数组指针排序(注意)
int cmp4(const void **a, const void **b)
{
    int *x = (int *)(*a); // 注意区别!!
    int *y = (int *)(*b);
    if (y[1] == x[1]) { // 特性二相同,按照特性1进行降序
        return y[0] - x[0];
    }
    return y[1] - x[1]; // 按照特性二降序
}
//二维数组指针排序
int **arr4 = (int **)malloc(sizeof(int *)* 3); // 三组数据:每组数据两个特性
for (i = 0; i < 3; i++) {
    arr4[i] = (int *)malloc(sizeof(int) * 2);
    for (j = 0; j < 2; j++) {
        arr4[i][j] = i + j;
    }
}
qsort(arr4, 3, sizeof(arr4[0]), cmp4);
/*排序结果
arr4
2 3
1 2
0 1
*/

2.5 字符串排序

//字符串数组排序
int cmp5(const void *a, const void *b)
{
    char *x = *(char **)a;
    char *y = *(char **)b;
    return strcmp(x, y);
}
char *strs[3] = {"shn", "abc", "axy"};
qsort(strs, 3, sizeof(char *), cmp5);
/*排序结果
strs:
abc axy shn
*/

2.6 结构体中使用qsort排序

typedef struct arrInfo{
    int data;
    int index;
} ArrInfo;

//结构体变量排序
int cmp6(const void *a, const void *b)
{
    ArrInfo *x = (ArrInfo *)a;
    ArrInfo *y = (ArrInfo *)b;
    if (y->data == x->data) { // 特性一data相同,按照特性二index进行降序
        return y->index - x->index;
    }
    return y->data - x->data; // 按照特性一data降序
}
//结构体中字段排序
ArrInfo *arr6 = (ArrInfo *)malloc(sizeof(ArrInfo)* 3); // 三组数据:每组数据两个特性
for (i = 0; i < 3; i++) {
    arr6[i].data = i;
    arr6[i].index = i + 1;
}
qsort(arr6, 3, sizeof(ArrInfo), cmp6);
/*排序结果
arr6
2 3
1 2
0 1
*/

2.7 结构体多级排序

根据学生信息,按照身高降序,身高相同时按照体重降序,体重也相同时按照姓名进行升序;

typedef struct StuInfo{
    char name[20];
    int high;
    int weight;
} StudentInfo;

//学生信息排序
int cmp7(const void *a, const void *b)
{
    StudentInfo *x = (StudentInfo *)a;
    StudentInfo *y = (StudentInfo *)b;
    if (y->high== x->hight) { // 身高相同,按照体重进行降序
        if (y->weight == x->weight) { // 体重相同,按照姓名首字母进行升序
            return strcmp(x->name, y->name);
        }
        return y->weight - x->weight;
    }
    return y->high- x->high; // 按照身高降序
}
//学生信息排序
StudentInfo arr7[5] = {{"shn", 170, 65},
                       {"xz",175, 80},
                       {"axz",170, 65},
                       {"dxz",175, 90},
                       {"we",170, 60},}; // 5个学生
qsort(arr7, 5, sizeof(StudentInfo), cmp7);
/*排序结果
arr7
dxz 175 90
xz 175 80
axz 170 65
shn 170 65
we 170 60
*/

为了加强对qsort使用理解,可以练习力扣937题。

【总结分享和大家共同进步】

若存在错误之处,欢迎批评指正,若有收获,欢迎关注点赞~

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值