作者:~小明学编程
文章专栏:C语言基础知识
目之所及皆为回忆,心之所想皆为过往
今天给大家介绍C语言中一个比较好用的函数qsort函数以及我们模拟实现qsort函数的过程。
目录

这里是qsort函数的介绍,在这里简单的给大家翻译介绍一下
首先最上面说到它的作用,执行一个快速排序,qsort函数是一个排序函数,它的底层排序算法是快速排序。
void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
接着就是它的返回值和参数,我们可以看到这长长的一串,看着就头疼,不过也没大家想象的那么复杂,给大家介绍一下大家就明白了。
首先看我们的第一个参数base,就是一个我们待排序的数组,接着就是num,顾名思义就是我们数组元素的的大小,待排序元素的个数,然后就是width参数,也就是我们待排元素中每个元素的大小,最后就是int (__cdecl *compare )(const void *elem1, const void *elem2 )这是一个回调函数,其中compare是一个函数指针,函数的两个参数分别是elem1和elem2(类型是void*)返回值是int类型,最后qsort的返回类型是void型。
下面就给大家介绍一下qsot函数的用法
- //整数的比较
- int cmp1(const void* e1, const void* e2)
- {
- return *((int*)e1) - *((int*)e2);
- }
- //测试整数
- void test1()
- {
- int arr[5] = { 5,4,3,2,1 };
- int sz = sizeof(arr) / sizeof(arr[0]);
- my_qsort(arr, sz, sizeof(arr[0]), cmp1);
- for (int i = 0; i < 5; i++)
- {
- printf("%d ", arr[i]);
- }
- printf("\n");
-
- }
- int main()
- {
- test1();
- return 0;
- }
这个比较函数是需要我们自己去设计的,根据我们所比较的类型不同我们可以设计不同的比较函数
- //浮点数的比较
- int cmp2(const void* e1, const void* e2)
- {
- return *((double*)e1) - *((double*)e2);
- }
- //字符的比较
- int cmp3(const void* e1, const void* e2)
- {
- return *((char*)e1) - *((char*)e2);
- }
- //字符串的比较
- int cmp4(const void* e1, const void* e2)
- {
- return strcmp(*(char**)e1, *(char**)e2);
- }
- //结构体数字比较
- int cmp5(const void* e1, const void* e2)
- {
- return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
- }
- //结构体字符串比较
- int cmp6(const void* e1, const void* e2)
- {
- return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
- }
下面是我们对一个整数数组的排序

- //模拟实现qsort函数
- void swap(char* ch1, char* ch2, int sz)
- {
- for (int i = 0; i < sz; i++)
- {
- char tem = *ch1;
- *ch1 = *ch2;
- *ch2 = tem;
- ch1++;
- ch2++;
- }
- }
- void my_qsort(void* arr, int num, int size, int (*cmp)(const void* e1, const void* e2))
- {
- for (int i = 0; i < num; i++)
- {
- for (int j = 0; j < num - i - 1; j++)
- {
- //cmp((char*)arr + j * size, (char*)arr + (j + 1) * size)
- if (cmp((char*)arr + j * size, (char*)arr + (j + 1) * size))
- {
- swap((char*)arr + j * size, (char*)arr + (j + 1) * size, size);
- }
- }
- }
- }
其中我们判断大小之后要进行一个交换,交换的过程我们采用的是逐个字节进行交换,也就是我们的swap函数所实现的功能。
下面是我们对各种类型的比较
- #include
- #include
- #include
- struct Stu
- {
- int age;
- char name[20];
- };
- //整数的比较
- int cmp1(const void* e1, const void* e2)
- {
- return *((int*)e1)-*((int*)e2);
- }
- //浮点数的比较
- int cmp2(const void* e1, const void* e2)
- {
- return *((double*)e1) - *((double*)e2);
- }
- //字符的比较
- int cmp3(const void* e1, const void* e2)
- {
- return *((char*)e1) - *((char*)e2);
- }
- //字符串的比较
- int cmp4(const void* e1, const void* e2)
- {
- return strcmp(*(char**)e1, *(char**)e2);
- }
- //结构体数字比较
- int cmp5(const void* e1, const void* e2)
- {
- return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
- }
- //结构体字符串比较
- int cmp6(const void* e1, const void* e2)
- {
- return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
- }
-
- //模拟实现qsort函数
- void swap(char* ch1, char* ch2, int sz)
- {
- for (int i = 0; i < sz; i++)
- {
- char tem = *ch1;
- *ch1 = *ch2;
- *ch2 = tem;
- ch1++;
- ch2++;
- }
- }
- void my_qsort(void* arr, int num, int size, int (*cmp)(const void* e1, const void* e2))
- {
- for (int i = 0; i < num; i++)
- {
- for (int j = 0; j < num - i - 1; j++)
- {
- //cmp((char*)arr + j * size, (char*)arr + (j + 1) * size)
- if (cmp((char*)arr + j * size, (char*)arr + (j + 1) * size))
- {
- swap((char*)arr + j * size, (char*)arr + (j + 1) * size, size);
- }
- }
- }
- }
- //测试整数
- void test1()
- {
- int arr[5] = { 5,4,3,2,1 };
- int sz = sizeof(arr) / sizeof(arr[0]);
- my_qsort(arr, sz, sizeof(arr[0]), cmp1);
- for (int i = 0; i < 5; i++)
- {
- printf("%d ", arr[i]);
- }
- printf("\n");
-
- }
-
- //测试浮点数
- void test2()
- {
- double arr[5] = { 2.5,2.3,3.8,6.1,0.2 };
- int sz = sizeof(arr) / sizeof(arr[0]);
- my_qsort(arr, sz, sizeof(arr[0]), cmp2);
- for (int i = 0; i < 5; i++)
- {
- printf("%.1lf ", arr[i]);
- }
- printf("\n");
- }
- //测试字符
- void test3()
- {
- char arr[5] = { 'e','f','o','a','q' };
- int sz = sizeof(arr) / sizeof(arr[0]);
- my_qsort(arr, sz, sizeof(arr[0]), cmp3);
- for (int i = 0; i < 5; i++)
- {
- printf("%c ", arr[i]);
- }
- printf("\n");
- }
- //测试字符串
- void test4()
- {
- char* arr[] = { "shan","huani","ajfie","deygufefb" };
- int sz = sizeof(arr) / sizeof(arr[0]);
- my_qsort(arr, sz, sizeof(arr[0]), cmp4);
- for (int i = 0; i < sz; i++)
- {
- printf("%s ", arr[i]);
- }
- printf("\n");
- }
- //测试结构体中的排序
- void test5()
- {
- struct Stu arr[4] = { {11,"uheriu"},{37,"iuehen"},{8,"aouenioon"},{22,"ming"} };
- int sz = sizeof(arr) / sizeof(arr[0]);
- my_qsort(arr, sz, sizeof(arr[0]), cmp5);
- for (int i = 0; i < sz; i++)
- {
- printf("%d ", arr[i].age);
- }
- printf("\n");
- my_qsort(arr, sz, sizeof(arr[0]), cmp6);
- for (int i = 0; i < sz; i++)
- {
- printf("%s ", arr[i].name);
- }
- }
- int main()
- {
- test1();
- test2();
- test3();
- test4();
- test5();
- return 0;
-
- }
