目录
回调函数
如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数
时,被调⽤的函数就是回调函数
回调函数在指针3的转移表我们就用到了回调函数
回调函数是就一个函数
下面在代码我们可以看到,把add函数的地址传给了p函数,p用函数指针接收命名为x,
然后可以通过x把a和b的数值传过去给add,然后返回值给 r 然后打印
x里存放的是add函数的地址
这就是一个回调函数
qsort函数
下面是冒泡排序,冒泡排序只能排序整形,无法排序浮点和字符还有结构体,我们就
需要用到qsort函数来进行排序
//冒泡排序
void add(int arr[], int sz)
{
for (int i = 0; i < sz-1; i++)
{
for (int j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int r = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = r;
}
}
}
}
int main()
{
int arr[] = { 2,4,6,8,10,1,3,5,7,9 };
int sz = sizeof(arr) / sizeof(arr[0]);
add(arr, sz);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
qsort函数的使用
qsort函数我们需要传4个参数(指向数组第1个元素的指针(首元素),元素个数值,元素类型大小,比较函数)
比较函数的参数为什么使用void*类型呢,因为void*可以接收全部参数,,但是比较数值必须要强制类型转换。
比较这2个数值的时候,(第1个值比第2个值大就返回大于0的数字(1))(第1个值比第2个小就返回小于0的数字(-1))(第1个值等于第2个值返回0)
返回大于1的话就交换这2个数值,小于等于不交换
qsort排序整行
整行排序我们可以使用减法
返回数值这个函数,为什么要用减法呢
因为x如果大于y,x减y的话就会得到大于0的数字
如果x小于y,x减y就会得到小于0的数值,
等于的话x减y就是0了
//返回数值
int add(const void* x, const void* y)
{
return *(int*)x - *(int*)y;
}
int main()
{
//要排序的数组
int arr[] = { 2,4,6,8,10,1,3,5,7,9 };
//计算元素个数
int sz = sizeof(arr) / sizeof(arr[0]);
//qsort函数
qsort(arr, sz, sizeof(arr[0]), add);
//打印
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
当然也可以这样写
//返回数值
int add(const void* x, const void* y)
{
//大于
if (*(int*)x > *(int*)y)
{
return 1;
}
//小于
else if (*(int*)x < *(int*)y)
{
return -1;
}
//等于
else
{
return 0;
}
}
int main()
{
//要排序的数组
int arr[] = { 2,4,6,8,10,1,3,5,7,9 };
//计算元素个数
int sz = sizeof(arr) / sizeof(arr[0]);
//qsort函数
qsort(arr, sz, sizeof(arr[0]), add);
//打印
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
qsort结构体排序
结构体姓名排序(字符串排序)
结构体年龄排序(整行排序)
这个可以和整行使用减法
//结构体
struct xs
{
//姓名
char xm[20];
//年龄
int nl;
};
//int add(const void* x, const void* y)
//{
// //按姓名来排序
// return strcmp(((struct xs*)x)->xm,((struct xs *)y)->xm);
//}
int add(const void* x, const void* y)
{
//按年龄来排序
return ((struct xs*)x)->nl - ((struct xs*)y)->nl;
}
int main()
{
struct xs arr[3] = { {"zhangsan",15} ,{"lisi",25},{"xiaomin",22} };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), add);
for (int i=0; i < sz; i++)
{
printf("%s\n%d\n", arr[i].xm,arr[i].nl);
}
}
模拟qsort函数
main函数还是和用来一样,来看模拟qsort函数
mn_qsort函数接收了4个参数,有2个无符号整行size_t,
2个for循环比较2个数值,和冒泡排序一样
b i j函数把 (char*)arr + j * f 和 (char*)arr + ( j + 1 ) * f 传给比较函数进行比较,大于0就交换
比较这2个数值的时候,(第1个值比第2个值大就返回大于0的数字(1))(第1个值比第2个小就返回小于0的数字(-1))(第 1个值等于第2个值返回0)
返回大于1的话就交换这2个数值,小于等于不交换
比较函数
交换函数
因为这是通用的交换方法,我们需要用char类型的指针进行交换,
为什么不用int指针类型的呢,因为如果用int的话,加1跳过4个字节,我们交换char类型的时候,char是1个字节,如果我们用int就会跳4个字节,所以我们要用char指针类型的
size_f是类型大小,这数组是int指针类型的我们就需要循环4次
//比较函数
int fh(const void*x,const void*y)
{
//强制类型转换成char*然后解引⽤
return (*(char*)x) - (*(char*)y);
}
//交换函数
int jh(char* x, char* y,size_t f)
{
for (int i = 0; i < f; i++)
{
char r = *x;
*x = *y;
*y = r;
x++;
y++;
}
}
// 数组首元素地址,元素个数, 类型大小 比较函数
void mn_qsort(void* arr[], size_t sz, size_t f, int(*bij)(int*, int*))
{
//循环比较2个数值和冒泡排序一样
for (int i = 0; i < sz - 1; i++)
{
for (int j = 0; j < sz - 1 - i; j++)
{
// 传参给比较函数 判断是不是大于0
if (bij((char*)arr + j * f, (char*)arr + (j + 1) * f) > 0)
{
//大于0,传参给交换函数 类型大小
jh((char*)arr + j * f, (char*)arr + (j + 1) * f, f);
}
}
}
}
int main()
{
int arr[] = { 2,4,6,8,10,1,3,5,7,9 };
int sz = sizeof(arr) / sizeof(arr[0]);
//模拟实现qsort函数
mn_qsort(arr, sz, sizeof(arr[0]), fh);
//打印
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[0] + i);
}
}