一.什么是qsort函数?
简单来说,qsort函数是库函数,就是用来排序的。
不过,qsort不仅仅可以用来排序整形数字,还可以用来排序小数,结构体,等等任意类型的数据。它的功能是十分强大的。
二.qsort函数的参数
qsort函数需要四个参数才能执行功能。
void qsort(void* base, size_t num, size_t size, int (*compar)(const void*, const void*))
我来分别解释一下这四个参数所代表的意义。
void* base:指针,指向的是待排序的数组的第一个元素。
size_t num:是base指向的待排序数组的元素个数。
size_t size :base 指向的待排序数组的元素的大小。
int (*compar)(const void*, const void*):是函数指针,指向的是用来比较两个元素的函数
三.简单写一个代码来实现qsort函数
为了让大家更好的理解这个函数的功能,在这里我先写一个代码简单用一下这个函数。
当然,用来排序结构体也是可以的。
在这里我写的结构体有两种排序方式,可以用字符串排序,也可以用年龄排序,这里我演示了用字符串排序的方式,用年龄排序也是换汤不换药。大家感兴趣可以试一试。
这里也是成功的进行了排序。看到这里可以大家会有疑问,这个函数到底是怎么把这个东西排好的?而且return *(int*)p1 - *(int*)p2 这个东西是怎么回事?
四.深刻的探讨qsort内部
咱们其实可以重新写一个模仿qsort函数的另一个函数bubble_sort,这个函数可以排任意类型的数据。这里我将用这个新函数来让大家更加深刻的了解qsort,解答大家对这个函数的困惑。
大家可以先看一下整体的代码
#include<stdio.h>
#include <stdlib.h>
#include <string.h>
void swap(char* buf1, char* buf2, size_t width)
{
for (int i = 0; i < width; i++)
{
char tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;
}
}
void bubble_sort(void* base, size_t sz, size_t width, int(*cmp)(const void* p1, const void* p2))
{
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
for (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 test3()
{
int arr[] = { 5,6,8,9,7,1,2,4,3,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
print(arr, sz);
}
int main()
{
test3();
return 0;
}
大家可以看到在这串代码中我又重新定义了一个函数swap,就是交换两个数据的意思。然而对于这个函数的参数大家可能会有疑问了,交换交换说的是两个数据交换,为什么后面还有一个width呢?这是干嘛的?
大家可以看前两个参数buf1和buf2,它们两个是字符指针,大家可以想一想我们仅仅把它们两个的地址传过去够不够?这两个数据交换的到底是多长的数据?
咱们知道指针的大小是固定的一直都是4个字节,然而我们给某一个指针加一的时候加的只是一个字节,我们通过中间变量tmp交换的也只是一个字节的量,此时我们就需要通过挨个交换实现整个大数据的交换,所以后面会出现buf1++和buf2++。
在此之后呢,我们所创建的新函数bubble_sort的四个参数就和qsort的四个参数都是相同的。
在这里我们相当于创建了一个新函数来变相的剖析qsort函数。
感谢大家的驻留观看,如果有错误和不足的地方,请高抬贵脚踢我一下,指正一下,非常感谢。
作者感言
关于qsort函数应该是大一的我目前为止所学习的最难的一个函数(作者是菜鸡)。我已经尽可能的去理解这个函数了。从昨天下午开始写这篇博客,加上今晚的一个小时时间,我也尽可能把我所理解的部分写了下来,如果有不足的地方,请多多指正