目录
一、前言
二、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()函数的理解,如果有不懂和发现问题的小伙伴,请在评论区说出来哦,同时我还会继续更新对结构体的理解,请持续关注我哦!!!!!?
?
|