qsort函数排序

一、认识qsort函数

在我们不了解qsort之前,冒泡排序可能是我们最常用的一种排序方法,但是冒泡排序法可用的范围太小了,比如需要排序结构体中的成员时自己动手拓展也会很麻烦。

这时候我们可以了解一下qsort排序函数,让我们变的更高级一点哈哈哈。

我们可以从库函数网站www.cplusplus.com中认识到这个qsort,首先运用这个函数之前我们要使用相应的头文件#include

接着我们来了解一下qsort的组成:

qsort函数排序_第1张图片

qsort函数中用到了四个参数,我们首先来了解一下这四个参数的意思

qsort函数排序_第2张图片解释:1、void*base:待排序数组的第一个元素。

           2、size_t num:待排序数组的元素个数。

           3、size_t size:待排序数组中一个元素的大小。

           4、int (*compar)(const void*,const void*):函数指针—compar指向了一个函数,这个函数是用来比较两个元素的大小。

这里可能会有朋友们感到疑惑,为什么1、4参数类型要用void*类型的指针,我们先来解答一下这个:

      void*:1、void*类型的指针—不能进行解引用操作符,也不能进行+-整数的操作,因为我们并不知道他是什么类型。

                  2、void*类型的指针是用来存放任意类型数据的地址(形象点来说就是垃圾桶)。

     我们之所以在这里用void*类型的指针,就是qsort函数并不知道你要排序的是什么类型的,所以可以用void*类型的指针来存放我们想要排序类型数据的地址,这样看来,qsort函数的范围确实是大于普通冒泡排序的范围的。

二、使用qsort函数

int arr[10] = { 10,9,8,7,6,5,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
print_arr(arr, sz);
qsort(arr, sz, sizeof(arr[0]), ???);

我们定义好一个数组之后,根据以上对qsort函数参数的解释,我们可以写出对相应的实参,前三个实参对于我们来说是很简单的,但是对于int (*compar)(const void*,const void*) 这个比较函数我们会有点摸不着头脑:这个是要自己写的?

当然,这个并不是qsort函数自带的,不是自带的又如何,写出一个比较函数还不是简简单单吗。

三、比较函数的编写

      

 我们先拿int型数组举例:

int cmp_int(const void* e1, const void* e2)
{
    return *(int*)e1 - *(int*)e2;
}

此时我们需要比较的是int型的元素,所以我们将e1、e2强制转化为int*类型的指针,再解引用得到元素相减即可比较出大小。如下:

int arr[10] = { 10,9,8,7,6,5,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
print_arr(arr, sz);
qsort(arr, sz, sizeof(arr[0]), cmp_int);

结果:

qsort函数排序_第3张图片

如果只有int型的排序那还是太逊啦。

假如我们想排序结构体中的元素呢?这时候我们可以再写一个比较函数,来进行结构体成员的比较

定义结构体:

struct stu
{
	char name[30];
	int age;
};
 
  

初始化结构体:

struct stu arr[] = { {"zhangsan",20},{"lisi",18},{"wangwu",22} };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]),???);

结构体成员有名字和年龄两个,这两个我们都可以比较吗,答案是肯定的。只要比较函数写的好,什么都可以比较。

比较年龄:

int cmp_struct_stu(const void* e1, const void* e2)
{
	return ((struct stu*)e1)->age - ((struct stu*)e2)->age;
}

           这个大致与int型数组元素的比较差不多,需要注意的是怎么指向结构体中的成员。

结果:

qsort函数排序_第4张图片

比较名字:这里我们按名字首字母先后顺序比较。

int comp_by_stu_name(const void* e1, const void* e2)
{
	return (strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name));
}

这里需要注意的是,我们在比较字符串的时候,需要用的是strcmp函数来比较,并且要用到其对应的头文件#include

结果:

qsort函数排序_第5张图片

      

读完的小伙伴可能会发现,为什么都是升序呢?如果我想降序呢?

我们拿int型数组举例:

int cmp_int(const void* e1, const void* e2)
{
	return *(int*)e2 - *(int*)e1;
}
我们只需要将原来的e1-e2,改为e2-e1就好了,也就是说,return返回值大于0则升序,小于0则降序。

重新定义arr数组:

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
print_arr(arr, sz);
qsort(arr, sz, sizeof(arr[0]), cmp_int);
print_arr(arr, sz);
return 0;

打印结果:

qsort函数排序_第6张图片

四、总结

综上,qsort对我们的帮助要更为大一些,因为它适用的范围更大,用起来也更为方便。

认识qsort函数还不够,我会带你去深入了解qsort

下次我们来讲怎样用冒泡排序来实现我们的qsort函数,了解qsort函数是怎样实现排序的

你可能感兴趣的:(算法,数据结构,c#)