在模拟实现qsort函数之前,我们先来浅浅了解一下qsort函数
void qsort (void* base, size_t num, size_t size, int (*compar)(const void e1*,const void e2*))
base 起始地址
num 元素个数
size 元素大小
compar 比较函数
e1 元素1
e2元素2
返回值 | 含义 |
<0 | e1 |
=0 | e1=e2 |
>0 | e1>e2 |
与冒泡排序做对比
//冒泡排序
#include
void bubble_sort(int arr[], int sz)
{
int i = 0;
for (i = 0; i arr[j +1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
void print(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
int i = 0;
int arr[10] = { 10,9,8,7,6,5,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr,sz);
print(arr, sz);
return 0;
}
由此可见,冒泡函数只需起止地址和元素个数即可,过度具体化,只能排序整形数组。
再来康康qsort函数
用qsort给数组进行排序
#include
#include
int cmp(const void* e1, const void* e2)
{
return *(int*)e1 - *(int*)e2;//void*类型的指针不能解引用,所以需强制类型转化为int*
}
int main(){
int i = 0;
int arr[10] = { 10,9,8,7,6,5,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp);
for (i = 0; i < sz; i++)
{
printf("%d", arr[i]);
}
return 0;
}
用qsort函数对结构体进行排序
//按年龄排
#include
#include
struct stu {
char name[10];
int age;
double score;
};
int cmp(const void* e1, const void* e2)
{
return ((struct stu*)e1)->age - ((struct stu*)e2)->age;
}
int main()
{
struct stu s[3] = { { "zhangsan",10,98},{"lisi",20,99},{"wangwu",25,100}};
int sz = sizeof(s) / sizeof(s[0]);
qsort(s, sz, sizeof(s[0]), cmp);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%s %d %.2lf\n", s[i].name, s[i].age, s[i].score);
}
return 0;
}
因此 我们可以看出在使用qsort函数时,只需将cmp函数中的void*类型的指针强制转换为所需类型,即可完成排序。(void*类型的指针是通用型,可以接受任意类型的指针,但是无法进行指针运算,所以在使用时要转换为相应的数据类型)
模拟实现qsort函数
struct stu
{
char name[10];
int age;
double score;
};
void swap(char* buff1, char* buff2,int width)//交换函数
{
int i = 0;
for (i = 0; i < width; i++)
{
char temp = *buff1;
*buff1 = *buff2;
*buff2 = temp;
buff1++;
buff2++;
}
}
int cmp(const void* e1, const void* e2)//比较函数
{
return ((struct stu*)e1)->age - ((struct stu*)e2)->age;
}
void my_bubble_sort( void* base, int num,int width, int(*cmp)(const void* e1, const void* e2))//注意第四个参数,由于传递上来的是cmp函数的地址,所以需用函数指针来接收
{
int i = 0;
int j = 0;
for (i = 0; i < num-1; i++)//确定排序的趟数
{
for (j = 0; j < num - 1-i; j++)//每一趟要比较多少次
{
if (cmp((char*)base + j* width, (char*)base + (j + 1)* width) > 0)//强制转换为char*类型的指针,加多少就代表跳过几个字节
{
swap((char*)base + j * width,(char*)base + (j + 1)* width,width);
}
}
}
}
int main()
{
struct stu s[3]={{ "zhangsan" ,10, 99.0}, {"lisi",30,89.0} ,{"wangwu",20,100} };//定义结构体数组
int sz = sizeof(s) / sizeof(s[0]);
my_bubble_sort(s, sz, sizeof(s[0]), cmp);//用qsort函数的逻辑传递参数
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%s %d %.2lf\n", s[i].name,s[i].age,s[i].score);
}
return 0;
}