一 回调函数
回调函数就是一个通过函数指针调用的函数。函数作为另外一个函数参数时,被调用的函数就是回调函数。
void qsort(void* base, //base 待排序的第一个元素;
size_t num, //num 待排序元素个数;
size_t size, //size 待排序元素大小,单位是字节;
int(*compar)(const void*, const void*) //compar是函数指针,指向的函数能够比较2个元素;
);void* (地址垃圾桶)通用指针类型,可接收任意类型地址,不支持指针加减或解应用;
int a = 10;
int* p = &a;
// char* p = &a; 类型不符报错
void* p = &a; //void*即使类型不符仍然不会报错
1,对整形数组排序
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h> //包含一个输入输出的文件
#include <stdlib.h>
#include <string.h>
int com_int(const void*e1, const void*e2)
{
return *(int*)e1 - *(int*)e2;
}
void print(int* p, int sz)
{
for (int i = 0; i < sz; i++)
printf("%d ", *p++);
}
void test1()
{
int arr[] = { 4,3,5,6,3,6,7,8,1,9,2 };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), com_int);
print(arr, sz);
}
int main()
{
test1();
return 0;
}
2,对字符串排序
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h> //包含一个输入输出的文件
#include <stdlib.h>
#include <string.h>
int arr_string_arrange(const void* e1, const void* e2)
{
return strcmp((char*)e1, (char*)e2);
}
void print_char(char * arr, int sz)
{
for (int i = 0; i < sz; i++)
printf("%c ", *arr++);
printf("\n");
}
int main()
{
char brr[] = "addcefagb";
int sz1 = sizeof(brr) / sizeof(brr[0]);
qsort(brr, sz1, sizeof(brr[0]), arr_string_arrange);
print_char(brr, sz1); // a a b c d d e f g
return 0;
}
3,构造函数排序
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h> //包含一个输入输出的文件
#include <stdlib.h>
#include <string.h>
struct Stu //描述学生
{
char name[20]; //名字
int age; //年龄
};
// 假设按年龄比较
int cmp_stu_by_age(const void *e1, const void* e2) //必须转成需要的类型
{
// struct Stu* 构造函数指针对象; (struct Stu*)e1 这只是临时的,因此要括起来
return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
int cmp_stu_by_name(const void* e1, const void* e2)
{
return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
void test2()
{
struct Stu s[] = { {"zhangsan",10},{"lisi",50},{"wangwu",20} };
int sz = sizeof(s) / sizeof(s[0]);
// qsort(s,sz,sizeof(s[0]), cmp_stu_by_age);
qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
}
int main()
{
test2();
return 0;
}
二 构造qsort通用方法
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h> //包含一个输入输出的文件
#include<string.h>
int cmp(const void* e1, const void* e2)
{
return *(int*)e1 - *(int*)e2;
}
Swap(char* buf1, char* buf2, size_t width)
{
for (int i = 0; i < width; i++) //对每个字节都去排序
{
int tmp = *buf1; //传尽量地址接收,然后交换变量
*buf1 = *buf2;
*buf2 = tmp;
buf1++; buf2++;
}
}
void bubble_sort(void* base, size_t sz, size_t width, int(*cmp)(const void* e1, const void* e2))
{
for (int i = 0; i < sz - 1; i++)
{
for (int j = 0; j < sz - 1 - i; j++)
{
if (cmp((char*)base + j * width, ((char*)base + (j + 1) * width)) > 0) { //判断大小
Swap((char*)base + j * width, ((char*)base + (j + 1) * width), width); //交换变量
}
}
}
}
void print_arr(int arr[], int sz)
{
for (int i = 0; i < sz; i++)
printf("%d ", arr[i]);
printf("\n");
}
void test1()
{
int arr[] = { 5,2,4,1,6,9,3,7,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz, sizeof(arr[0]), cmp);
print_arr(arr, sz);
}
struct Stu
{
char name[20];
int age;
};
int cmp_stu_age(const void* e1, const void* e2)
{
return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
int cmp_stu_name(const void* e1, const void* e2)
{
return (strcmp(((struct Stu*)e1)->name , ((struct Stu*)e2)->name));
}
void test2()
{
struct Stu arr2[] = { {"zhangsan",30},{"lisi",80},{"wangwu",20} };
int sz = sizeof(arr2) / sizeof(arr2[0]);
bubble_sort(arr2, sz, sizeof(arr2[0]), cmp_stu_age); //根据年龄排序
bubble_sort(arr2, sz, sizeof(arr2[0]), cmp_stu_name); //根据名字排序
for (int i = 0; i < sz; i++)
{
printf("%d %s\n", arr2[i].age, arr2[i].name);
}
}
int main()
{
//test1(); //排序整数
test2(); //排序构造函数
}