qsort是一个库函数,本文内容就是模拟实现qsort
思路:本质还是排序!
排序有很多种办法,我选了冒泡排序来实现
排序的基本逻辑也和冒泡一样
不一样的点:交换数据的函数和比较函数
这也是为什么可以实现任意类型的排序
交换数据:
因为不清楚交换数据的类型,所以采用一个字节一个字节进行交换
我们怎么知道要交换几个字节?用sizeof算元素大小呗
比较函数(cmp函数):
这个函数是自定义的,需要根据类型的不同具体写出不同的函数
比如:返回值大于0对应大于的情况
返回值小于0对应小于的情况
返回值等于0对应等于的情况
如果上述规则对应升序,那么反过来就对应降序(把cmp函数的两个指针交换一下)
为什么my_qsort() 有四个参数?
(qsort也有四个参数)
第一个参数决定了排序的起始地址,第二和第三个参数决定了排序范围,第四个参数决定了比较的方式和比较到底是升序还是降序
int cmp_int(const void* e1, const void*e2)
{//以排序整型为例的cmp函数
return *((int*)e1) - *((int*)e2);
}
void my_swap(char* e1, char *e2 ,int width)//需要width,cmp函数是需要自己构造,所以不用传width
//不需要再定义为void 已经确定逐字节交换
{
for (int i = 0; i < width; i++)
{
char tmp = *e1;
*e1 = *e2;
*e2 = tmp;
e1++;
e2++;
}
}
void my_qsort(void* base,int sz,int width,int (*cmp)(const void*e1,const void* e2))
{
for (int i = 0; i < sz; i++)
{
for (int j = 0; j < sz - 1-i; j++)
{
if (cmp((char*)base + j*width, (char*)base + (j + 1)*width)>0)
{
my_swap((char*)base + j*width, (char*)base + (j + 1)*width,width);
}
}
}
}
以一道例题和一个乱序的数组作为测试用例
例题:一张成绩单上有成绩和名字,一个成绩对应一个名字,现在要求对成绩单进行排序,如何实现?
struct student
{
char name[50];
int grade;
};
int cmp_int(const void* e1, const void*e2)
{
return *((int*)e1) - *((int*)e2);
}
int cmp_stu_int(const void*e1, const void* e2)
{
return ((student*)e1)->grade - ((student*)e2)->grade;
}
int cmp_name(const void* e1, const void* e2)
{
return strcmp((char*)e1, (char*)e2);
}
void my_swap(char* e1, char *e2 ,int width)
{
//需要width,cmp函数是需要自己构造,所以不用传width
//不需要再定义为void 已经确定逐字节交换,也即确定字符型
for (int i = 0; i < width; i++)
{
char tmp = *e1;
*e1 = *e2;
*e2 = tmp;
e1++;
e2++;
}
}
void my_qsort(void* base,int sz,int width,int (*cmp)(const void*e1,const void* e2))
{
for (int i = 0; i < sz; i++)
{
for (int j = 0; j < sz - 1-i; j++)
{
if (cmp((char*)base + j*width, (char*)base + (j + 1)*width)>0)//比较
{
my_swap((char*)base + j*width, (char*)base + (j + 1)*width,width);//交换
}
}
}
}
void pr1(int* arr,int sz)
{
for (int i = 0; i < sz; i++)
{
printf("%d ", *(arr + i));
}
printf("\n");
}
void test1()
{
int arr[] = { 0, 9, 8, 2, 6, 5, 3, 4, 1, 7 };
int sz = sizeof(arr) / sizeof(arr[0]);
my_qsort(arr, sz, sizeof(arr[0]), cmp_int);
pr1(arr, sz);
}
void pr2(student* ans,int sz)
{
for (int i = 0; i < sz; i++)
{
printf("%s %d\n", (ans + i)->name, (ans + i)->grade);
}
printf("\n");
}
void test2()
{
student s[] = { { "red", 50 }, { "yellow", 40 }, { "blue", 80 } };
int sz = sizeof(s) / sizeof(s[0]);
//my_qsort(s, sz, sizeof(s[0]), cmp_name);
my_qsort(s, sz, sizeof(s[0]), cmp_stu_int);
pr2(s,sz);
}
int main()
{
test1();
test2();
return 0;
}
如果想试试上述函数的效果如何?可以拷贝到自己编译器试试哦!
总结
排序任何类型的本质还是排序,不过是数据的交换和比较方式不同而已
针对这两个问题:
数据的交换问题:逐字节交换
比较方式的问题:结合返回值来自己构造规则
只要会构造cmp函数就能使用qsort函数了,要是还会冒泡和数据交换那你自己就可以写出自己的qsort实现任何类型的排序了
-------
如果有启发的话,留个赞再走吧,这对我帮助很大!
不点?