当前位置:网站首页>qsort — c语言中自带的排序函数(附带void*、回调函数知识点
qsort — c语言中自带的排序函数(附带void*、回调函数知识点
2022-07-27 05:03:00 【vpurple__】
因为总是忘记有qsort这个函数,导致遇到需要排序的题的时候,总是要写着类似的代码,所以特此单独把qsort拿出来单独整理一遍,让自己能够熟练掌握,也以免之后忘记了qsort可以拿自己的文章看。
目录
一、论冒泡排序和qsort
冒泡排序的核心思想:相邻元素两两比较
写一个冒泡排序函数:
#include<stdio.h>
void bubble_sort(int arr[], int sz);//函数声明
int main()
{
//先创建一个数组
int arr[] = { 4,8,9,3,5,2,1,7 };
//通过sizeof求元素个数
int sz = sizeof(arr) / sizeof(arr[0]);
//把数组排成升序
bubble_sort(arr, sz);
//打印数组内容
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
//这个函数只能排整型数组
void bubble_sort(int arr[], int sz)
{
int i = 0;
while (sz)
{
int flag = 0;
for (i = 0; i < sz - 1; i++)
{
if (arr[i] > arr[i + 1])//元素两两比较
{
int tmp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = tmp;
flag = 1;
}
}
sz--;
if (flag == 0)
{
break;//如果数组内容一开始就是按规则有序排列的,可以进行判断优化
}
}
}请注意:这样的冒泡排序有一个弊端只能排序整型数据,因为在最开始函数定义的时候已经把参数写死了。
下面开始介绍一个库函数qsort
1、qsort 是什么?
qsort是一个使用快速排序的思想实现的一个排序函数。
并且qsort 可以排序任意类型的数据。
下面是关于qsort函数参数的介绍:
void qsort(void* base, size_t num, size_t size,
int (*cmp)(const void* e1, const void* e2));
//
//void* base 你要排序的数据的起始位置
//size_t num 待排序的数据元素的个数
//size_t size 待排序的数据元素的大小(单位是字节)
//int (*cmp)(const void* e1, const void* e2))
//函数指针-比较函数 cmp就是一个比较函数的地址,也就是这个比较函数的函数指针
//e1指向了你要比较的第一个元素 e2指向了你要比较的第二个元素
//e1 e2 是你要比较的两个元素的地址
2、qsort在程序中使用
写一个程序使用一下:
#include<stdio.h>
#include<stdlib.h>
int cmp_int(const void* e1, const void* e2);
int main()
{
//先创建一个数组
int arr[] = { 4,8,9,3,5,2,1,7 };
//通过sizeof求元素个数
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp_int);
//打印数组内容
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
//比较两个整型元素
//这样排序默认是升序排列
//
int cmp_int (const void*e1,const void*e2)
{
return (* (int*)e1 - *(int*)e2);//所以比较的时候要强制类型转换一下
}1.关于cmp函数的一些规定
注意其对于函数参数所传递的void*指针的解应用需要进行强制类型转换,比较什么类型的数据,就强制类型转换成什么类型,随后进行比较。
注意返回值规定:
//e1指向的元素 > e2指向的元素 返回值 >0
//e1指向的元素 = e2指向的元素 返回值 =0
//e1指向的元素 < e2指向的元素 返回值 <0
默认这样传递返回值,是升序排列。
//这样排序默认是升序排列
//
int cmp_int (const void*e1,const void*e2)
{
return (* (int*)e1 - *(int*)e2);//所以比较的时候要强制类型转换一下
}
//注意规定:
//e1指向的元素 > e2指向的元素 返回值 >0
//e1指向的元素 = e2指向的元素 返回值 =0
//e1指向的元素 < e2指向的元素 返回值 <0
如果想要变成降序排列
可以改变e1 e2相减位置,或者直接整体加负号使其逻辑相反即可。
//如果想改成降序排列
//可以改变e1 e2相减位置,或者直接整体加负号使其逻辑相反即可
int cmp_int(const void* e1, const void* e2)
{
return -(*(int*)e1 - *(int*)e2);
}插入一个知识点:
2、介绍一个指针类型 void*类型
论void*的包容性:
void*的指针是无具体类型的指针,可以接受任意类型的地址。是不能直接进行解应用操作的,也不能进行+ -整数的操作。
注意在使用指针指向的内容的时候,要对其强制类型转换再解引用。
3、模拟qsort
注意在my_qsrt中向cmp传参时的强制类型转换:
在这里传参比较的时候不能直接传递void*类型的 arr,void*类型的数据不能加减操作。
将void*类型强制转换成最小类型char*类型,后续根据len进行步长的加减。
根据cmp返回参数规定,以及qsort默认排列升序,所以是 >0。
//模拟qsort
#include<stdio.h>
void my_qsort(void* arr, int sz, int len, int cmp(void* e1, void* e2));
int cmp_int(const void* e1, const void* e2);
int main()
{
int arr[] = { 1,2,5,4,7,8,6,3,9 };
int sz = sizeof(arr) / sizeof(arr[0]);
my_qsort(arr, sz, sizeof(arr[0]), cmp_int);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return;
}
int cmp_int (const void*e1,const void*e2)
{
return (* (int*)e1 - *(int*)e2);
}
void my_qsort(void* arr, int sz, int len, int cmp(const void* e1, const void* e2))
{
int i = 0;
while (sz)
{
int flag = 0;
for (i = 0; i < sz - 1; i++)
{
//注意这里传参比较的时候不能直接传递arr,void*类型的数据不能加减操作
//将void*类型强制转换成最小类型char*类型,后续根据len进行步长的加减
//根据cmp返回参数规定,以及qsort默认排列升序,所以是 >0
if (cmp((char*)arr + len * i, (char*)arr + len * (i + 1) )> 0)
{
int tmp = *((char*)arr + len * i);
*((char*)arr + len * i) = *((char*)arr + len * (i + 1));
*((char*)arr + len * (i + 1)) = tmp;
flag = 1;
}
}
sz--;
if (flag == 0)
{
break;
}
}
}
二、回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个 函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。
!注意:回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。(就比如在使用qsort函数的时候调用的cmp函数
三、在最后
第一次写完一个正式的关于知识点的博客,vpurple表示自己很开心哈哈哈,这次费的时间还挺长的,还是对这个编辑器运用不熟练www,不过在写这个博客的时候又重新复习了一遍,真的希望要把它记在心里呜呜呜
反思一下其实我对于c语言后半部分的知识点基本功都不太扎实,还是要趁着暑假期间把它们全都顺一遍,坚持日更!!!flag反正是立在这里了www绝对不会打脸的!!!
还有在最后祝我早日对于qsort函数使用烂熟于心,还有void*和回调函数这些知识点,全都记住!!!
边栏推荐
猜你喜欢

Flask框架创建项目初期总结

Li Hongyi machine learning team learning punch in activity day04 - Introduction to deep learning and back propagation mechanism

mq设置过期时间、优先级、死信队列、延迟队列

C语言初阶——分支语句(if,switch)

初识C语言——常量、变量

Rolling Division

用户的管理-限制

异步数据-短信验证码

初始C语言——关键字static的作用

How to quickly and effectively solve the problem of database connection failure
随机推荐
B1028 census
Dnsmasq Usage Summary
强制登录,七牛云上传图片
Numpy data type conversion
初识C语言——初识指针
How to quickly and effectively solve the problem of database connection failure
MQ set expiration time, priority, dead letter queue, delay queue
Collation of several difficult methods in pytorch --gather & squeeze & unsqueeze
Hi3516dv300 environment setup
Common commands in CONDA and pip environments
Differences among bio, NiO and AIO
Redis lock
Notes Series docker installation PostgreSQL 14
The concept of cloud native application and 15 characteristics of cloud native application
Pinball games
封装JWT
GCC 编译选项
Student management system
conda和pip环境常用命令
李宏毅机器学习组队学习打卡活动day03---误差和梯度下降