个人主页:
仍有未知等待探索_数据结构,小项目,C语言疑难-CSDN博客
专题分栏:
目录
一、引言
第一个参数是void*base:指向要排序的数组的第一个对象的指针,转换为 void*。
第二个参数是size_t num:数组中按基数指向的元素数。size_t是无符号整数类型。
第三个参数是size_t size:数组中每个元素的大小(以字节为单位)size_t是无符号整数类型。
第四个参数是int (*compar)(const void*p1,const void*p2)):指向比较两个元素的函数的指针。
大家是不是很疑惑,咱们写冒泡排序或者选择排序的时候,感觉也没有那么的复杂,为什么C语言库函数中qsort函数的参数那么的麻烦。为什么还要传size_t size呢?大家是不是会有这样的疑问呢?今天我就给大家详细的讲解一下!(库函数中qsort函数是快速排序,我用冒泡排序实现)
二、讲解实现
1、给整型数组排序
首先,我们需要先把自定义函数的参数给设计好,但是因为我们是实现库函数中的qsort函数,所有我们就直接把库函数中的参数写出来就行了。
我们现在要排序的是整型数组,所以也需要一个整型数组。
sz是为了计算出数组的长度。
问:为什么自定义函数的接收数组的参数类型是void*,而不是int*呢?
答:void* 是一种无类型指针,可以指向任意类型的数据,无需强制类型转换。意思就是说,当你把数组arr传给void*base的时候,不用管为什么base的类型不是int*,可以把void*类型理解为一个万能的类型。(注意:void*类型的变量,不能直接进行解引用访问,也不能进行指针运算,想进行上述操作必须进行强制类型转化)
#includeint cmp(void* x, void* y){return *(int*)x - *(int*)y;}//声明自定义排序函数void qsort_m(void* base, size_t num, size_t size,int (*compar)(const void* p1, const void* p2));int main(){int arr[] = { 9,8,7,6,5,4,3,2,1 };//提供一个整型数组int sz = sizeof(arr) / sizeof(arr[0]);//计算数组的长度qsort_m(arr, sz, sizeof(arr[0]), cmp);//自定义排序函数的调用int i = 0;for (i = 0; i < sz; i++)//输出printf("%d ", arr[i]);return 0;}
排序实现
void qsort_m(void* base, size_t num, size_t size, int (*compar)(const void* p1, const void* p2)){int i = 0, j = 0;for (int i = 0; i < num - 1; i++){for (int j = 0; j < num - 1 - i; j++){if (compar(((char*)base + j * size), (char*)base + (j + 1) * size) > 0){//交换swap((char*)base + j * size, (char*)base + (j + 1) * size,size);}}}}
compar(((char*)base + j * size), (char*)base + (j + 1) * size),这块要把base强转为char*类型,目的是这个char*能表示更多的数据类型,char*解引用仅能得到一个字节的数据,而int*等其他的类型解引用之后,能得到更多的字节的数据均比char*的大,所以用char*类型可以得到所有传进来的数据,所以,到这里就明白了,为什么要传入数据类型的大小,j*size是为了让数组访问下一个空间的数据。
最后就剩一个比较简单的交换函数。
void swap(char* buf1, char* buf2, size_t size){int i = 0;for (int i = 0; i < size; i++){int tmp;tmp = *(buf1 + i);*(buf1 + i) = *(buf2 + i);*(buf2 + i) = tmp;}}
总代码
#includeint cmp(void* x, void* y){return *(int*)x - *(int*)y;}void swap(char* buf1, char* buf2, size_t size);void qsort_m(void* base, size_t num, size_t size, int (*compar)(const void* p1, const void* p2));int main(){int arr[] = { 9,8,7,6,5,4,3,2,1 };//提供一个整型数组int sz = sizeof(arr) / sizeof(arr[0]);//计算数组的长度qsort_m(arr, sz, sizeof(arr[0]), cmp);//自定义排序函数的调用int i = 0;for (i = 0; i < sz; i++)//输出printf("%d ", arr[i]);return 0;}void qsort_m(void* base, size_t num, size_t size, int (*compar)(const void* p1, const void* p2)){int i = 0, j = 0;for (int i = 0; i < num - 1; i++){for (int j = 0; j < num - 1 - i; j++){if (compar(((char*)base + j * size), (char*)base + (j + 1) * size) > 0){//交换swap((char*)base + j * size, (char*)base + (j + 1) * size,size);}}}}void swap(char* buf1, char* buf2, size_t size){int i = 0;for (int i = 0; i < size; i++){int tmp;tmp = *(buf1 + i);*(buf1 + i) = *(buf2 + i);*(buf2 + i) = tmp;}}
2、qsort中参数cmp函数怎么实现
cmp是一个函数指针,这个函数指针指向的是一个函数,这个函数的返回值是int类型的。当返回值<0 ,p1 指向的元素先于 p2 指向的元素 ;返回值=0 ,p1 指向的元素等效于 p2 指向的元素;返回值 >0 ,p1 指向的元素在 p2 指向的元素之后。
如果想详细的知道的话,请点链接,看我上一篇。
C语言qsort函数的使用_仍有未知等待探索的博客-CSDN博客
1.浮点型
int cmp(const void* p1, const void* p2){return *(float*)p1 - *(float*)p2;}
2.结构体类型
typedef struct Stu{char name[20];int score;}Stu;int cmp(const void* p1, const void* p2){return ((Stu*)p1)->score - ((Stu*)p2)->score;}int main(){Stu s[3] = { { "张三",50 }, { "王五",70 }, { "李四",60 } };int sz = sizeof(s) / sizeof(s[0]);qsort(s, sz, sizeof(s[0]), cmp);for (int i = 0; i < sz; i++)printf("%s %d\n", s[i].name,s[i].score);return 0;}
最后、谢谢大家的支持 !
来源地址:https://blog.csdn.net/qq_73435980/article/details/133203433