我们知道包含stdlib.h头文件后,就可以使用qsort这个库函数,接下来让我们了解他。
#qsort 函数介绍及举例使用
qsort第一个参数是要排序的数组的首地址,第二个参数是要排序的数据数量,有几个,第三个参数是要排序的那个参数占几个字节,最后一个参数是函数指针,是让用户进行使用的函数,可以让用户对任意类型数据进行排序,一会儿我们会说到。
快速排序,可以实现像冒泡排序等的排序,同时能够对结构体排序时,将其其他数据一同排序,这是他的一大优点,接下来看举例:
#include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct Qsort { char name[8]; int age; }Qsort; int cmp(void* p1, void* p2) { return ((Qsort*)p1)->age - ((Qsort*)p2)->age; } int main() { Qsort People[3]; memset(People, 0, sizeof(Qsort) * 3); for (int i = 0; i < 3; i++) { scanf("%s %d", People[i].name, &People[i].age); getchar(); } qsort(People,3,sizeof(Qsort), cmp); for (int i = 0; i < 3; i++) { printf("%s %d\n", People[i].name, People[i].age); } return 0; }
运行截图如下:
实现了年龄的排序,同时将名字也进行了移动,非常好用,接下来再举几个例子:
Example 1:对整数排序
#include <stdio.h> #include <stdlib.h> int cmp(const void* a, const void* b) { return *(int*)a - *(int*)b; } int main() { int arr[10] = { 1,2,3,7,3,1,5,9,2,5 }; qsort(arr, 10, sizeof(int), cmp); for (int i = 0; i < 10; i++) { printf("%d ", arr[i]); } return 0; }
Example 2:对浮点数排序
#include <stdio.h> #include <stdlib.h> int cmp(const void* a, const void* b) { return *(float*)a - *(float*)b; } int main() { float farr[5] = { 3.14,5.20,13.14,6.6,11.1 }; qsort(farr, 5, 4, cmp); for (int i = 0; i < 5; i++) { printf("%.2f\n", farr[i]); } return 0; }
Example 3:对名字排序
#include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct Qsort { char name[8]; int age; }Qsort; int cmp(void* p1, void* p2) { return strcmp(((Qsort*)p1)->name , ((Qsort*)p2)->name); } int main() { Qsort People[3]; memset(People, 0, sizeof(Qsort) * 3); for (int i = 0; i < 3; i++) { scanf("%s %d", People[i].name, &People[i].age); getchar(); } qsort(People,3,sizeof(Qsort), cmp); for (int i = 0; i < 3; i++) { printf("%s %d\n", People[i].name, People[i].age); } return 0; }
你学会如何使用qsort了吗?如果还有疑问,接下来在qsort的模拟实现中也许会解答你的疑问惑
#qsort函数模拟实现
这里的核心排序我们将使用冒泡排序替代,这里本应该使用快速排序作为核心,但这里不涉及数据结构,就不多做介绍,感兴趣可以自己使用快速排序
#include <stdio.h> #include <string.h> #include <assert.h> typedef struct stu { char name[20]; int age; }stu; int cmp(void* p1, void* p2); void my_qsort(void* base, size_t num, size_t sz, int (*cmp)(const void* ,const void*)); void swap(char* a, char* b, int sz); int main() { //qsort(base,num,size,cmp) stu student[3] = { {"nene",23},{"haha",21},{"miao",22} }; my_qsort(student, 3, sizeof(stu), cmp); for (int i = 0; i < 3; i++) { printf("%s %d\n", student[i].name, student[i].age); } return 0; } //因为我们不知道要比较的数据是什么类型,所以干脆传viod*类型,这样用户使用时 //想比较什么类型的数据自己强制转换就好,就是用cmp函数,将void*类型的参数强 //制转换成int*等类型,解引用后返回差值,或者是大小,返回的值将作为是否进行 //数据交换的依据。 void my_qsort(void* base, size_t num, size_t sz, int (*cmp)(const void*, const void*)) { assert(base); //断言,判断传上来的指针是否为NULL for (int i = 0; i < num - 1; i++) { for (int j = 0; j < num - i - 1; j++) { if (cmp((char*)base + sz * j, (char*)base + sz * (j + 1)) > 0) swap((char*)base + sz * j, (char*)base + sz * (j + 1), sz); //在这里,根据cmp的返回值决定是否交换 } } } int cmp(void* p1, void* p2) { return strcmp(((stu*)p1)->name, ((stu*)p2)->name); } //这个函数我们的参数设置为char*,因为我们依然不知道用户想要排序什么 //类型的数据,但是我们交换时不能用void*,void*可以接受任何类型的数据 //但是他没有大小,不能解引用,所以传上来sz这个大小,然后每个字节进行交换 void swap(char* a, char* b, int sz) { assert(a && b); while (sz--) { char temp = *a; *a = *b; *b = temp; a += 1; b += 1; } }
#下期预告
指针进阶知识:
1.字符指针
2.指针数组
3.数组指针
4.一维数组传参,一级指针传参,区别
二维数组传参,二级指针传参,区别