目录
一.回调函数
二.qsort函数
三.void*指针
四.用qsort函数进行升序排序
1.整形数组排序
2.结构体数组排序
3.字符数组排序
五.使用冒泡排序模拟实现qsort函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个
函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数
的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进
行响应。
qsort是一个函数,基于快速排序算法实现的一个排序函数。
这是MSDN上面的介绍:
void qsort(void* base, //待排序数据的起始位置
size_t num, //数组的元素个数
size_t width, //一个元素的字节大小
int(*cmp)(const void* elem1, const void* elem2)//cmp是一个函数指针,指向一个比较函数,需
//要自己编写,elem1,elem2是两个待比较元素的地址
返回值大小 注意:排序整形数据可以用> <,但排序结构体数据可能不方便用> <比较了。
相当于通用的指针类型,可以存放指向任何类型的指针,当你的函数参数类型不确定时,可以使用 void *,不能解引用和+-整数运算。
int i_cmp (const void* e1, const void* e2) //qsort默认升序排序,想要降序排序只需要调
换e1和e2即可
{
return *((int*)e1) - *((int*)e2); //void*指针不能解引用,需要强制类型转换为int*型
}
void print(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), i_cmp);
print(arr, sz);
return 0;
}
struct Stu
{
char name[20];
int age;
double score;
};
int j_cmp_by_age(const void* e1, const void* e2)
{
return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
//int j_cmp_by_name(const void*e1,const void* e2)
//{
// return strcmp( ((struct Stu*)e1)->name , ((struct Stu*)e2)->name) //字符串比较大小要使
用strcmp函数
//}
int main()
{
struct Stu stu[3] = { {"lisi",20,70.2},{"wangwu",23,88.5},{"zhangsan",18,90.2}};
int sz = sizeof(stu) / sizeof(stu[0]);
qsort(stu, sz, sizeof(stu[0]), j_cmp_by_age); //通过年龄来排序
//qsort(stu,sz,sizeof(stu[0]), j_cmp_by_name); //通过姓名来排序
printf("%s %d\n", stu[0].name, stu[0].age);
printf("%s %d\n", stu[1].name, stu[1].age);
printf("%s %d\n", stu[2].name, stu[2].age);
return 0;
}
strcmp返回值大小和qsort函数返回值恰好一样,srtcmp函数比较2个字符串大小,一个字符一个字符进行比较,按ASCII值比较大小。
int f_cmp(const void* e1, const void* e2)
{
return *((char*)e1) - *((char*)e2);
}
void print(char arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%c ",arr[i]);
}
}
int main()
{
char arr[] = "dfesagc";
int sz = strlen(arr);
qsort(arr, sz, sizeof(arr[0]), f_cmp);
print(arr, sz);
return 0;
}
int cmp(const void* e1, const void* e2)
{
return *(int*)e1 - *(int*)e2;
}
void Swap(char* buff1, char* buff2, int width)
{
int i = 0;
for (i = 0; i < width; i++)
{
char tmp = *buff1;
*buff1 = *buff2;
*buff2 = tmp;
buff1++;
buff2++;
}
}
//因为交换的时候是传地址,所以要知道元素的宽度,一个字节一个字节的交换 ,这样也证明了使用char*指
//针的好处!
void bubble_sort(void* base, int num, int width, int (*cmp)(void* e1, void* e2))
{
int i = 0;
for (i = 0; i < num - 1; i++) //趟数
{
int j = 0;
for (j = 0; j < num - 1 - i; j++)
{
if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
//升序排序
//j = 0时,比较的是第一个元素和第二个元素
// j = 1时,比较的是第二个元素和第三个元素
{
Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
//交换
}
}
}
}
void test()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
bubble_sort(arr, sz, sizeof(arr[0]), cmp);
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
test();
return 0;
}