文章目录
并不是很重要的废话
qsort到底是什么
(不过是一个 头文件是<stdlib.h>的用于排序的超好用的函数罢辽)
先放一个函数原型压压惊
void qsort( void *ptr, size_t count, size_t size,
int (*comp)(const void *, const void *) );
看不懂也没关系,稍后会进行分解
看看就行系列
- 在c的文档里,对qsort是这样描述的
翻译一下重点就是,qsort函数是按升序对给定数组进行排序,而原型中出现的函数用于对象的比较。 - 再看看文档对原型中出现的comp函数是怎么解释的
下面会进行详解,这里就不翻译啦
这才是正文
详解函数原型
void qsort( void *ptr, size_t count, size_t size,
int (*comp)(const void *, const void *) );
qsort的函数原型包含四部分,分别是:
- 指向待排序数组的指针(使用的时候传个地址进去哦)
- 数组里元素的数量
- 数组中每个元素的大小
- 比较函数(这个在下面单独讲解)
举个例子
//假设现在有一个数组 a
int a[] = { 2,5,3,6,1,4 };
//将要对a进行排序,那么在调用qsort的时候就是这样的
qsort(a, 6, 4, comp);
//但是其实我更喜欢写成👇这个样子
qsort(a, sizeof(a) / sizeof(a[0]), sizeof(int), comp);
- 第一个a,自然就是数组a的地址
- 第二个6,是指数组a里面现在有6个数字
- 第三个4,是在64位机上,int类型占用4个字节(所以直接sizeof(int),不用记类型的大小更方便)
- 第四个函数马上就说
详解comp
来看看这个嵌在qsort原型里面的comp原型
int (*comp)(const void *, const void *);
comp存在的意义
每个函数都有它存在的意义。而这个comp的意义,就是用于对象的比较。说白了,我们要通过编写comp函数来决定qsort如何对数组进行排序。
comp的作用途径
总结一下文档里的描述,用人话说就是
-
如果comp返回正整数,那么qsort会交换传入的两个元素的位置
-
如果comp返回负整数,那么qsort不会交换传入的两个元素的位置
而我们编写comp就是在决定什么时候要交换位置,什么时候不交换位置
所以学会使用qsort最关键的就是学会编写comp
comp到底应该怎么写
总结一下就两步
- 强制转换指针的类型
- 在某种情况下返回整数值
举个例子(这个排出来是降序哦)
int compare(const void* a, const void* b) {
//第一步强制转换
int* pa = (int*)a;
int* pb = (int*)b;
//第二步根据想交换的情况返回值
if (*pa < *pb) {
return 1;
}
else {
return -1;
}
}
- comp其实就是一个函数,叫什么无所谓(不一定叫comp,像例子里叫compare也是可以的)
- 记得一定一定要对指针进行类型的转换,因为传进来的时候,类型是void
- 在返回的时候,有些会习惯写成
return *pa-*pb;
的形式,但是这种形式要注意的小点比较多,而且不够清晰,本篇博客就不用这种形式写了
一大波例子正在靠近
对double型数组进行排序
double a[] = { 1.0,4.2,6.3,3.0,5.0,8.0,9.0,6.4 };
int compare(const void* a, const void* b) {
double* pa = (double*)a;
double* pb = (double*)b;
if (*pa < *pb) {
return 1;
}
else {
return -1;
}
}
不能写成return *pa - *pb;
因为返回类型是int,这样相减的结果会被强制转换成int,导致结果出错
比如上面这个例子,运行的结果会是👇
对字符串指针数组进行排序
char* a[4] = { (char*)"hi", (char*)"happy", (char*)"in", (char*)"3g" };
int compare(const void* a, const void* b) {
char* pa = *(char**)a;
char* pb = *(char**)b;
return strcmp(pa, pb);
}
一般对字符串排序都是从小到大,如果pa<pb,strcmp会返回负数,qsort不会进行交换,恰好满足了需求,直接返回strcmp结果就行。
对结构体数组一级排序
typedef struct people {
int num1;
int num2;
}People;
People a[3] = { {1,2},{3,6},{3,5}};
int compare(const void* a, const void* b) {
People* pa = (People*)a;
People* pb = (People*)b;
if (pa->num1 < pb->num1) return -1;
else return 1;
}
对结构体数组进行二级排序
typedef struct people {
int num1;
int num2;
}People;
People a[3] = { {1,2},{3,6},{3,5}};
int compare(const void* a, const void* b) {
People* pa = (People*)a;
People* pb = (People*)b;
if (pa->num1 < pb->num1) {
return -1;
}
else if (pa->num1 > pb->num1) {
return 1;
}
else {
if (pa->num2 < pb->num2) {
return -1;
}
else {
return 1;
}
}
}