• C语言qsort()函数针对:整型、单个字符、字符串、结构体,超详细讲解(多维度分析举例,小白一看就懂!!!!!)


    目录

    一、前言

    二、qsort()函数

     🍑qsort()函数简介

    🍉qsort()函数中整型、double型、字符型的应用

    💦整型

    💦 double型

    💦字符排序 

     🍎qsort()函数在字符串中的应用

    💦在字符串中按首字母排序

    💦字符串长度排序

    💦字符串按字典顺序排序 

    🍓结构体排序的应用

    💦结构体多级排序

     三、共勉


    一、前言

        在我了解到qsort()函数之前呢,对于我这个编程小菜狗来说,平时练习排序的时候就只会用到冒泡排序(代码复杂,且时间复杂度高),并且大部分只会应用到整型数据的排序,一旦遇到字符、字符串、结构体、或者要求时间复杂度的题题目时,基本可以说是两眼一抹黑,完全滴不会。于是,为了解决这一排序问题,我专门花了一早上的时间去研究全能的排序函数qsort()函数,在这里做出总结,希望对大家有用O!!!!

    二、qsort()函数

     🍑qsort()函数简介

        排序方法有很多种:选择排序,冒泡排序,归并排序,快速排序等。 看名字都知道快速排序是目前公认的一种比较好的排序算法。因为它速度很快,所以系统也在库里实现这个算法,便于我们的使用。 这就是qsort函数(全称quicksort)。它是ANSIC标准中提供的,其声明在stdlib.h文件中,是根据二分法写的,其时间复杂度为n*log(n)。

    知识点1:

    qsort()函数的头文件:#include

    qsort()函数的声明:

     函数声明的解释:

    1. #include
    2. #include
    3. void qsort (void* base, size_t num, size_t size,int (*compar)(const void*, const void*));

     各个参数的理解:

    void *base:void  指向任意类型的数据   *base 为待排序数组的起始位置的数据

    size_t num:数组元素个数

    size_t size :待排序元素数据的大小 (举例:int 型是4  ,char型是 1)

    int (*compar)(const void*, const void*)  比较两个元素大小的函数指针----判断升序或降序

    (此函数功能需要我们自己编写实现)

     加const表示无法改变指针指向的值。

     return * ( int * )a - * ( int * ) b ,返回一个整型数,表示两个元素对比的结果。如果a大于b,则返回正数。a小于b,则返回负数。如果a等于b,则返回零。

    (int *)表示将地址强制类型转换成整形地址类型,可根据排序对象选择指针类型的转换。

    如果大家还想了解更加详细的qsort()函数的声明可以进入这个网站了解:

    qsort - C++ Reference (cplusplus.com)

    🍉qsort()函数中整型、double型、字符型的应用

    💦整型

    知识点1:

    首先写出针对整型的 比较函数: int (*compar)(const void*, const void*)

    1. int cmp_int (const void * a,const void *b) //整型
    2. {
    3. int* a = (int*)_a; //强制类型转换
    4. int* b = (int*)_b;
    5. return *a - *b; // 升序
    6. return *b - *a; // 降序
    7. }

    上面写的这种方法便于大家的理解,其实可以继续化简,使代码更加简洁

    1. int cmp_int (const void * a,const void *b)
    2. {
    3. return * (int * )a-* (int *)b; //升序
    4. return * (int * )b-* (int *)a; //降序
    5. }

    知识点2:

    针对整型数据的排序举例,看代码:

    1. #include
    2. #include
    3. int cmp_int(const void* a, const void* b)
    4. {
    5. return *(int*)a - *(int*)b; //升序
    6. }
    7. int main()
    8. {
    9. int arr[] = { 1, 3, 6, 2, 4, 8, 7, 10 };
    10. printf("排序前:");
    11. int sz = sizeof(arr) / sizeof(arr[0]); //求出数组的长度
    12. for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
    13. {
    14. printf("%d ", arr[i]);
    15. }
    16. qsort(arr, sz, sizeof(arr[0]), cmp_int); // 进行排序
    17. printf("\n排序后:");
    18. for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
    19. {
    20. printf("%d ", arr[i]);
    21. }
    22. return 0;
    23. }

    💦 double型

    知识点1:

    首先写出针对整型的 比较函数: int (*compar)(const void*, const void*)

    1. int cmp_double (const void * a, const void * b)
    2. {
    3. return *(double *)a > *(double *)b ? 1 : -1; //升序
    4. return *(double *)a < *(double *)b ? 1 : -1; //降序
    5. }

    注意:

     这里两个浮点数相减但要返回一个整型数,如果按上面做法直接减会丢失小数点部分。所以需另加处理,直接判断大小,如果a大于b,则返回1,否则返回-1。

    知识点2:
     针对double型数据的排序举例,看代码:

    1. #include
    2. #include
    3. int cmp_double(const void* a, const void* b)
    4. {
    5. return *(double*)a > *(double*)b ? 1 : -1; //升序
    6. }
    7. int main()
    8. {
    9. double arr[] = { 1.0, 3.0, 6.0, 2.0, 4.0, 8.0, 7.0, 10.0 };
    10. printf("排序前:");
    11. int sz = sizeof(arr) / sizeof(arr[0]); //求出数组的长度
    12. for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
    13. {
    14. printf("%.2lf ", arr[i]);
    15. }
    16. qsort(arr, sz, sizeof(arr[0]), cmp_double); //进行排序
    17. printf("\n排序后:");
    18. for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
    19. {
    20. printf("%.2lf ", arr[i]);
    21. }
    22. return 0;
    23. }

     

    💦字符排序 

    知识点1:
    首先写出针对整型的 比较函数: int (*compar)(const void*, const void*)

    1. int cmp_char(const void *a,const void *b)
    2. {
    3. return *(char *)a - *(char *)b; //升序
    4. return *(char *)a - *(char *)b; //降序
    5. }

    知识点2:

    针对double型数据的排序举例,看代码:

    1. #include
    2. #include
    3. int cmp_char(const void* a, const void* b)
    4. {
    5. return *(char*)a - *(char*)b; //升序
    6. }
    7. int main()
    8. {
    9. char arr[] = { 'b', 'd', 'a', 'c' };
    10. printf("排序前:");
    11. int sz = sizeof(arr) / sizeof(arr[0]); //求出数组的长度
    12. for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
    13. {
    14. printf("%c ", arr[i]);
    15. }
    16. qsort(arr, sz, sizeof(arr[0]), cmp_char); //进行排序
    17. printf("\n排序后:");
    18. for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
    19. {
    20. //printf("");
    21. printf("%c ", arr[i]);
    22. }
    23. return 0;
    24. }

     

     🍎qsort()函数在字符串中的应用

    💦在字符串中按首字母排序

    知识点1:
    首先写出针对整型的 比较函数: int (*compar)(const void*, const void*)

    1. int cmp_char(const void *a, const void *b)
    2. {
    3. return * (char *)a - *(char * )b; //升序
    4. }

    针对字符串按首字母的排序举例,看代码:

    1. #include
    2. #include
    3. #define L 10
    4. #define K 10
    5. int cmp_char(const void* a, const void* b)
    6. {
    7. return *(char*)a - *(char*)b; //升序
    8. }
    9. int main()
    10. {
    11. char a[L][K] = {
    12. "rbsc",
    13. "jcse",
    14. "efgd",
    15. "arbs",
    16. "bbs",
    17. "cbfe",
    18. "dgafg" ,
    19. "ewqrta",
    20. "ofgd",
    21. "mbcv",
    22. };
    23. qsort(a, L, sizeof(char) * K, cmp_char); // 进行排序
    24. for (int i = 0; i < L; i++)
    25. {
    26. printf("%s\n", a[i]);
    27. }
    28. return 0;
    29. }

    注意:此时先申请一个二维数组,将二维数组的每一行看成一个一维数组,就可以得出,有L个一维数组,每个数组有K个元素。

    💦字符串长度排序

    知识点1:
    首先写出针对整型的 比较函数: int (*compar)(const void*, const void*)

    1. int cmp_char(const void *a, const void *b)
    2. {
    3. return strlen((char *)a) > strlen((char *)b) ? 1 : -1; //升序
    4. }

    注:这里不要用 return strlen((char * )a) - strlen((char * )b) ;

    原因:1. strlen返回类型为size_t,size_t是标准C库中定义的,应为unsigned int,在64位系统中为 long unsigned int。无符号整型最好不要做四则运算。

              2. 这里虽然函数返回int型,会把无符号数转换为整型,但返回结果只在字符串的长度未超过int的范围时正确。这种大范围转小范围要考虑精度损失的问题。

             3.这里大家可以看看我之前写的字符串函数:

    (358条消息) C语言:常见字符串函数详解初阶(小白一看就懂,让你有一种相见恨晚的感觉哦!!!)_sunny-ll的博客-CSDN博客

    针对字符串长度排序举例,看代码:

    1. #include
    2. #include
    3. #include
    4. #define L 10
    5. #define K 10
    6. int cmp_char(const void *a, const void *b)
    7. {
    8. return strlen((char *)a) > strlen((char *)b) ? 1 : -1; //升序
    9. }
    10. int main ()
    11. {
    12. char a[L][K] = {
    13. "rbsc",
    14. "jcsse",
    15. "efgdsd",
    16. "arbs",
    17. "bbs",
    18. "cbfefaa",
    19. "dgafg" ,
    20. "ewqrta",
    21. "ofgd",
    22. "mbcv312",
    23. };
    24. qsort(a, L, sizeof(char) * K, cmp_char);
    25. for (int i = 0; i < L; i++)
    26. {
    27. printf("%s\n", a[i]);
    28. }
    29. }

    💦字符串按字典顺序排序 

    知识点1:

    首先写出针对整型的 比较函数: int (*compar)(const void*, const void*)

    1. int cmp_char(const void *a, const void *b)
    2. {
    3. return strcmp((char * )a, (char *)b); //升序
    4. }

    针对字符串字典顺序排序举例,看代码:

    1. #include
    2. #include
    3. #include
    4. #define L 10
    5. #define K 10
    6. int cmp_char(const void *a, const void *b)
    7. {
    8. return strcmp((char * )a, (char *)b); //升序
    9. }
    10. int main ()
    11. {
    12. char a[L][K] = {
    13. "rbsc",
    14. "jcsse",
    15. "afgdsd",
    16. "arbs",
    17. "abs",
    18. "cbfefaa",
    19. "cgafg" ,
    20. "ewqrta",
    21. "ofgd",
    22. "mbcv312",
    23. };
    24. qsort(a, L, sizeof(char) * K, cmp_char);
    25. for (int i = 0; i < L; i++)
    26. {
    27. printf("%s\n", a[i]);
    28. }
    29. }

    🍓结构体排序的应用

    💦结构体多级排序

    结构体体的三级排序测试:
    第一级是对学生成绩整体从小到大排序;
    第二级是对相同成绩的学生,按照姓名进行排序;
    第三级是对相同成绩、姓名的学生,按照学号进行排序;

    代码举例:

    1. #include
    2. #include
    3. #include
    4. typedef struct student //结构体类型
    5. {
    6. int id; //成绩
    7. char name[10]; //姓名
    8. int grade; //学号
    9. }student; // 结构体变量
    10. int cmp1(const void* a, const void* b)//一级排序 :对学生成绩整体从小到大排序
    11. {
    12. student* s1 = (student*)a; //指针强制转换为 结构体指针
    13. student* s2 = (student*)b;
    14. return s1->id - s2->id;
    15. }
    16. int cmp2(const void* a, const void* b)//二级排序:对相同成绩的学生,按照姓名进行排序
    17. {
    18. student* s1 = (student*)a;
    19. student* s2 = (student*)b;
    20. if (strcmp(s1->name, s2->name) != 0)
    21. return strcmp(s1->name, s2->name);
    22. else
    23. return s1->id - s2->id;
    24. }
    25. int cmp3(const void* a, const void* b)//三级排序 :对相同成绩、姓名的学生,按照学号进行排序
    26. {
    27. student* s1 = (student*)a;
    28. student* s2 = (student*)b;
    29. if (s1->grade != s2->grade)
    30. return s1->grade - s2->grade;
    31. else
    32. {
    33. if (strcmp(s1->name, s2->name) != 0)
    34. return strcmp(s1->name, s2->name);
    35. else
    36. return s1->id - s1->id;
    37. }
    38. }
    39. int main()
    40. {
    41. int i, N, C;
    42. scanf("%d %d", &N, &C);
    43. student* stu;
    44. stu = (student*)malloc(N * sizeof(student));
    45. for (i = 0; i < N; i++)
    46. scanf("%d %s %d", &stu[i].id, stu[i].name, &stu[i].grade);
    47. switch (C)
    48. {
    49. case 1: qsort(stu, N, sizeof(student), cmp1); break;//一级排序
    50. case 2: qsort(stu, N, sizeof(student), cmp2); break;//二级排序
    51. case 3: qsort(stu, N, sizeof(student), cmp3); break;//三级排序
    52. }
    53. printf("排序结果:\n");
    54. for (i = 0; i < N; i++)
    55. printf("%03d %s %d\n", stu[i].id, stu[i].name, stu[i].grade);
    56. return 0;
    57. }

     三、共勉

    以下就是我对C语言qsort()函数的理解,如果有不懂和发现问题的小伙伴,请在评论区说出来哦,同时我还会继续更新对结构体理解,请持续关注我哦!!!!! 

     

  • 相关阅读:
    【YOLOv7/YOLOv5系列算法改进NO.48】构建新的轻量网络—Slim-neck by GSConv(2022CVPR)
    Docker初体验之安装部署和镜像加速(openeuler版)
    使用MD5加密后的字符串存密码安全吗?你不得不了解的Hash算法
    JDK JRE JVM解释及Java代码编译运行过程
    【BOM】location对象
    【第3章】MyBatis-Plus持久层接口之Service Interface(上)
    php获取前端ajax数据对服务器json文件进行增改
    VCS工具学习笔记(4)
    Docker数据卷和网络管理 下
    git format-patch打补丁
  • 原文地址:https://blog.csdn.net/weixin_45031801/article/details/127587587