1.什么是qsort函数
2.qsort函数的使用
3.模拟实现qsort函数
1.1 什么是qsort函数
qsort函数是一种对数组进行排序的函数。 头文件为<stdlib.h>
不仅能对整数进行排序,也能对其他类型的数据进行排序如结构体,字符等等
1.2 qsort函数原型
void qsort
(void* base, size_t num, size_t size,
int (*compar)(const void*, const void*));
void* base 数组的起始地址一般传入的是数组名,num则是数组中元素的个数,size则是数组中元素的大小,而*compar则是一个函数指针决定了数组的排序。
1.3 关于compar函数,该函数要求返回大于0、小于0以及等于0的数,而这也决定了数组的排序。
代码如下;
int cmp_int(const void* p1, const void* p2)//整数调用qsort函数
{
return *(int*)p1 - *(int*)p2;//强制类型转换为int*并解引用
}
如若是p1-p2则是升序排列,若是p2-p1则是降序排列。
2.1 qsort函数的使用
要想调用qsort函数进行数组排序只需要根据上文的qsort函数模型相应的进行数据传入即可。比较值得注意的是compar中的(const void*, const void*),在com函数中的两个空指针将如何返回函数一个整数呢。这两个数据都是空指针又该如何调用呢。没错,这时候就要用强制类型转换将数据类型转换成我们所需要的能够达成我们要求的类型。
2.2 整型数组中qsort函数的使用
代码如下
int cmp_int(const void* p1, const void* p2)//整数调用qsort函数
{
return *(int*)p1 - *(int*)p2;//强制类型转换为int*并解引用 因为当p1大于p2时返回大于0的数当p1小于p2时返回小于零的数字
} //相等时返回0 若为降序将返回值反过来即可
int main()
{
int arr[10] = {5,6,8,7,1,3,4,2,9,10};
int sz = sizeof(arr[0]);
int size = sizeof(arr) / sizeof(arr[0]);
qsort(arr,size,sz, cmp_int);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
2.3 结构体中qsort函数的使用
struct stu
{
char name[20];
int age;
};
int com_str(const void*p1, const void*p2)
{
return strcmp(((struct stu*)p1)->name, ((struct stu*)p2)->name);//对姓名进行排序
return ((struct stu*)p1)->age- ((struct stu*)p2)->age;//对年龄进行排序
}
void test()
{
struct stu arr[3] = { {"zhangsan",19},{"lisi",34},{"wangwu",6} };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), com_str);
}
int main()
{
test();
return 0;
}
3.模拟用冒泡排序法实现qsort函数
在使用冒泡排序法模拟实现qsort函数时我们不妨先看看qsort函数的原型
void qsort(void* base, size_t num, size_t size,int (compar)(const void, const void*));
我们可以根据原型传入相对应的数据,创建函数时保持原函数的类型即可。那么为什么base不能时其他的类型呢?就非得是void*?这其实和qsort的特点有很大关系,qsort可以排序任意类型,因此这个类型不能够指定为具体的某一个类型。那么在接下来在调用时又出现了void不能调用的问题,既然要调用它void肯定不行,那么只好进行强制类型转换了。
代码具体如下
int cmp(const void* p1, const void* p2)
{
return *(int*)p1 - *(int*)p2;
}
void imp(void* beat, size_t num, size_t width, int (*comper)(const void* p1, const void* p2))
{
for (int i = 0; i < num - 1; i++)
{
for (int j = 0; j < num - 1 - i; j++)
{
if (comper((char*)beat + width * j, (char*)beat + width * (j + 1)) > 0)
{
swap((char*)beat + width * j, (char*)beat + width * (j + 1), width);
}
}
}
}
在这段代码中我们将它转化成了char类型的指针,这也是因为char指针可以存储一个字节的原因,在排序过程中我们可能会遇到排序7个字节的问题,如果这时使用int*或者其他类型可能会出现错误。
在冒泡排序中我们决定是否进行交换的条件是if(arr[0]>arr[1]),而现在模拟qsort函数时我们则需要将这两个值传入函数指针中,调用后经过判断在进入swap函数之中进行交换,width是void *beat单个数据所占字节的大小,加上width * j是让其随着j的移动而移动找到相对应的元素。
swap函数如下
void swap(char* p1, char* p2, int width)
{
for (int i = 0; i < width; i++)
{
char temp = *p1;
*p1 = *p2;
*p2 = temp;
p1++;
p2++;
}
利用指针将两个传入的数据进行交换
剩下的代码如下
void print(int arr[], int num)
{
for (int i = 0; i < num; i++)
printf("%d ", arr[i]);
}
void test()
{
int arr[10] = { 5,9,8,4,6,3,7,1,2,65 };
int sz = sizeof(arr) / sizeof(arr[0]);
int size = sizeof(arr[0]);
imp(arr, sz, size, cmp);
print(arr, sz);
}
int main()
{
test();
return 0;
}
本篇博客到此结束,如果各位觉得对自己有所帮助的话不要忘记一键三连哦