目录
一、前言
二、qsort()函数
🍑qsort()函数简介
🍉qsort()函数中整型、double型、字符型的应用
💦整型
💦 double型
💦字符排序
🍎qsort()函数在字符串中的应用
💦在字符串中按首字母排序
💦字符串长度排序
💦字符串按字典顺序排序
🍓结构体排序的应用
💦结构体多级排序
三、共勉
一、前言
在我了解到qsort()函数之前呢,对于我这个编程小菜狗来说,平时练习排序的时候就只会用到冒泡排序(代码复杂,且时间复杂度高),并且大部分只会应用到整型数据的排序,一旦遇到字符、字符串、结构体、或者要求时间复杂度的题题目时,基本可以说是两眼一抹黑,完全滴不会。于是,为了解决这一排序问题,我专门花了一早上的时间去研究全能的排序函数qsort()函数,在这里做出总结,希望对大家有用O!!!!
二、qsort()函数
🍑qsort()函数简介
排序方法有很多种:选择排序,冒泡排序,归并排序,快速排序等。 看名字都知道快速排序是目前公认的一种比较好的排序算法。因为它速度很快,所以系统也在库里实现这个算法,便于我们的使用。 这就是qsort函数(全称quicksort)。它是ANSIC标准中提供的,其声明在stdlib.h文件中,是根据二分法写的,其时间复杂度为n*log(n)。
知识点1:
qsort()函数的头文件:#include <stdlib.h>
qsort()函数的声明:
函数声明的解释:
#include <stdlib.h> #include <stdio.h> 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*)
int cmp_int (const void * a,const void *b) //整型 { int* a = (int*)_a; //强制类型转换 int* b = (int*)_b; return *a - *b; // 升序 return *b - *a; // 降序 }
上面写的这种方法便于大家的理解,其实可以继续化简,使代码更加简洁
int cmp_int (const void * a,const void *b) { return * (int * )a-* (int *)b; //升序 return * (int * )b-* (int *)a; //降序 }
知识点2:
针对整型数据的排序举例,看代码:
#include <stdlib.h> #include <stdio.h> int cmp_int(const void* a, const void* b) { return *(int*)a - *(int*)b; //升序 } int main() { int arr[] = { 1, 3, 6, 2, 4, 8, 7, 10 }; printf("排序前:"); int sz = sizeof(arr) / sizeof(arr[0]); //求出数组的长度 for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i) { printf("%d ", arr[i]); } qsort(arr, sz, sizeof(arr[0]), cmp_int); // 进行排序 printf("\n排序后:"); for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i) { printf("%d ", arr[i]); } return 0; }
💦 double型
知识点1:
首先写出针对整型的 比较函数: int (*compar)(const void*, const void*)
int cmp_double (const void * a, const void * b) { return *(double *)a > *(double *)b ? 1 : -1; //升序 return *(double *)a < *(double *)b ? 1 : -1; //降序 }
注意:
这里两个浮点数相减但要返回一个整型数,如果按上面做法直接减会丢失小数点部分。所以需另加处理,直接判断大小,如果a大于b,则返回1,否则返回-1。
知识点2:
针对double型数据的排序举例,看代码:#include <stdlib.h> #include <stdio.h> int cmp_double(const void* a, const void* b) { return *(double*)a > *(double*)b ? 1 : -1; //升序 } int main() { double arr[] = { 1.0, 3.0, 6.0, 2.0, 4.0, 8.0, 7.0, 10.0 }; printf("排序前:"); int sz = sizeof(arr) / sizeof(arr[0]); //求出数组的长度 for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i) { printf("%.2lf ", arr[i]); } qsort(arr, sz, sizeof(arr[0]), cmp_double); //进行排序 printf("\n排序后:"); for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i) { printf("%.2lf ", arr[i]); } return 0; }
💦字符排序
知识点1:
首先写出针对整型的 比较函数: int (*compar)(const void*, const void*)int cmp_char(const void *a,const void *b) { return *(char *)a - *(char *)b; //升序 return *(char *)a - *(char *)b; //降序 }
知识点2:
针对double型数据的排序举例,看代码:
#include <stdlib.h> #include <stdio.h> int cmp_char(const void* a, const void* b) { return *(char*)a - *(char*)b; //升序 } int main() { char arr[] = { 'b', 'd', 'a', 'c' }; printf("排序前:"); int sz = sizeof(arr) / sizeof(arr[0]); //求出数组的长度 for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i) { printf("%c ", arr[i]); } qsort(arr, sz, sizeof(arr[0]), cmp_char); //进行排序 printf("\n排序后:"); for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i) { //printf(""); printf("%c ", arr[i]); } return 0; }
🍎qsort()函数在字符串中的应用
💦在字符串中按首字母排序
知识点1:
首先写出针对整型的 比较函数: int (*compar)(const void*, const void*)int cmp_char(const void *a, const void *b) { return * (char *)a - *(char * )b; //升序 }
针对字符串按首字母的排序举例,看代码:
#include<stdio.h> #include<stdlib.h> #define L 10 #define K 10 int cmp_char(const void* a, const void* b) { return *(char*)a - *(char*)b; //升序 } int main() { char a[L][K] = { "rbsc", "jcse", "efgd", "arbs", "bbs", "cbfe", "dgafg" , "ewqrta", "ofgd", "mbcv", }; qsort(a, L, sizeof(char) * K, cmp_char); // 进行排序 for (int i = 0; i < L; i++) { printf("%s\n", a[i]); } return 0; }
注意:此时先申请一个二维数组,将二维数组的每一行看成一个一维数组,就可以得出,有L个一维数组,每个数组有K个元素。
💦字符串长度排序
知识点1:
首先写出针对整型的 比较函数: int (*compar)(const void*, const void*)int cmp_char(const void *a, const void *b) { return strlen((char *)a) > strlen((char *)b) ? 1 : -1; //升序 }
注:这里不要用 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博客
针对字符串长度排序举例,看代码:
#include<stdio.h> #include<stdlib.h> #include<string.h> #define L 10 #define K 10 int cmp_char(const void *a, const void *b) { return strlen((char *)a) > strlen((char *)b) ? 1 : -1; //升序 } int main () { char a[L][K] = { "rbsc", "jcsse", "efgdsd", "arbs", "bbs", "cbfefaa", "dgafg" , "ewqrta", "ofgd", "mbcv312", }; qsort(a, L, sizeof(char) * K, cmp_char); for (int i = 0; i < L; i++) { printf("%s\n", a[i]); } }
💦字符串按字典顺序排序
知识点1:
首先写出针对整型的 比较函数: int (*compar)(const void*, const void*)
int cmp_char(const void *a, const void *b) { return strcmp((char * )a, (char *)b); //升序 }
针对字符串字典顺序排序举例,看代码:
#include<stdio.h> #include<stdlib.h> #include<string.h> #define L 10 #define K 10 int cmp_char(const void *a, const void *b) { return strcmp((char * )a, (char *)b); //升序 } int main () { char a[L][K] = { "rbsc", "jcsse", "afgdsd", "arbs", "abs", "cbfefaa", "cgafg" , "ewqrta", "ofgd", "mbcv312", }; qsort(a, L, sizeof(char) * K, cmp_char); for (int i = 0; i < L; i++) { printf("%s\n", a[i]); } }
🍓结构体排序的应用
💦结构体多级排序
结构体体的三级排序测试:
第一级是对学生成绩整体从小到大排序;
第二级是对相同成绩的学生,按照姓名进行排序;
第三级是对相同成绩、姓名的学生,按照学号进行排序;代码举例:
#include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct student //结构体类型 { int id; //成绩 char name[10]; //姓名 int grade; //学号 }student; // 结构体变量 int cmp1(const void* a, const void* b)//一级排序 :对学生成绩整体从小到大排序 { student* s1 = (student*)a; //指针强制转换为 结构体指针 student* s2 = (student*)b; return s1->id - s2->id; } int cmp2(const void* a, const void* b)//二级排序:对相同成绩的学生,按照姓名进行排序 { student* s1 = (student*)a; student* s2 = (student*)b; if (strcmp(s1->name, s2->name) != 0) return strcmp(s1->name, s2->name); else return s1->id - s2->id; } int cmp3(const void* a, const void* b)//三级排序 :对相同成绩、姓名的学生,按照学号进行排序 { student* s1 = (student*)a; student* s2 = (student*)b; if (s1->grade != s2->grade) return s1->grade - s2->grade; else { if (strcmp(s1->name, s2->name) != 0) return strcmp(s1->name, s2->name); else return s1->id - s1->id; } } int main() { int i, N, C; scanf("%d %d", &N, &C); student* stu; stu = (student*)malloc(N * sizeof(student)); for (i = 0; i < N; i++) scanf("%d %s %d", &stu[i].id, stu[i].name, &stu[i].grade); switch (C) { case 1: qsort(stu, N, sizeof(student), cmp1); break;//一级排序 case 2: qsort(stu, N, sizeof(student), cmp2); break;//二级排序 case 3: qsort(stu, N, sizeof(student), cmp3); break;//三级排序 } printf("排序结果:\n"); for (i = 0; i < N; i++) printf("%03d %s %d\n", stu[i].id, stu[i].name, stu[i].grade); return 0; }
三、共勉
以下就是我对C语言qsort()函数的理解,如果有不懂和发现问题的小伙伴,请在评论区说出来哦,同时我还会继续更新对结构体的理解,请持续关注我哦!!!!!