qsort函数实现对任意数据的排序

Posted Aline2021-yxz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了qsort函数实现对任意数据的排序相关的知识,希望对你有一定的参考价值。

学会使用qsort函数排序

qsort介绍

qsort函数是一个库函数,它的作用是对数据进行排序,思想是:快速排序!

因为是库函数,所以在使用的时候需要引头文件:<stdlib.h>/<search.h>

我们可以通过以下的方式使用qsort函数:qsort( (void *)argv, (size_t)argc, sizeof( char * ), compare );
参数解释:
(void *)argv:你想要从哪个数组/结构体的哪个元素开始排序就将它的地址作为实参。

(size_t)argc:你想要排序的元素个数。

sizeof(char*):排序的元素大小;

compare:是一个函数指针,指向的函数是比较元素大小的,因为不同的数据的比较方法是不同的,所以在创建qsort函数的时候将比较方法抽离出来,需要我们编写。

假如我要使用qsort排序一个数组的全部元素,那么我在引用qsort的时候应该这么写:

#include<stdio.h>
#include<stdlib.h>

int main()

	int arr[] = 9,5,4,8,3,1,7,6,10,2 ;
	int sz = sizeof(arr) / sizeof(arr[0]);//计算数组每个元素的大小
	qsort(arr, sz, sizeof(arr[0]), compare);

	return 0;



如果我只想排序5到7共6个元素的时候那我该这么写:

#include<stdio.h>
#include<stdlib.h>

int main()

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

	return 0;



compare函数介绍

compare函数是qsort排序的核心

compare函数的定义形式: compare( const void* elem1, const void* elem2 )。

看到这里是不是感觉怪怪的?再引用compare函数的时候并没有参数啊,怎么这里有两个指针呢?我在接触到qsort的时候也有这样的疑问,于是我找到了qsort的函数原型:

static void __cdecl shortsort(char *lo, char *hi, size_t width,  
                                                          int (__cdecl *comp)(const void *, const void *));


static void __cdecl swap(char *p, char *q, size_t width);

可以看到compare确实是有两个指针的,至于elem1和elem2的地址是如何传进去的,博主也不太懂呢,需要去研究源码,但是我们知道它是把 (void *)argv的地址和 (void *)argv+1的地址传了过去,并且每次调用玩都会对地址进行加一操作,一直到(size_t)argc的地址为止,知道这些就足够我们使用qsort函数了。

从这张图片我们可以看到,当elem1指向的元素大于elem2指向的元素时compare函数会返回一个正值等于的时候会返回0小于的时候会返回负值,这对没深入理解compare函数的我们来说不知道返回正值、0、负值意味着什么,我们只需要记住这样的写法未来排序完成是升序的就行,如果想要降序加个负号或者交换两个指针的位置就可以了。

这里我想说一下void*指针,这个指针是一个万能指针,它可以接收任何类型的元素的地址,但是它也有美中不足的地方,那就是无法对这个指针进行任何的运算操作,像什么++,–,*等都是不行的,因为它没有类型,在进行这些操作时无法知道它该访问几个字节的内存,自然是无法进行操作。

不同的数据类型相应的比较函数定义

对数组元素为数字的:

int  compare(const void *e1,const void *e2)


	return  *(int*)e1 - *(int*)e2;//结果要返回正,0,负,那我干脆让它们相减。


#include<stdio.h>
#include<stdlib.h>

int main()

	int arr[] = 9,5,4,8,3,1,7,6,10,2 ;
	int sz = sizeof(arr) / sizeof(arr[0]);//计算元素个数
	qsort(arr, sz, sizeof(arr[0]), compare);
	int a = 0;
	for (a = 0; a < sz; a++)
	
		printf("%d\\n", arr[a]);
	
	return 0;


在return的时候将e1和e2指针进行了强制类型转换,因为void的指针是不能解引用的,又因为数组元素是int,所以转为int。
如果是小数如下,double也一样:

int  compare(const void *e1,const void *e2)


	return  (int)(*(float*)e1 - *(float*)e2);//将指针强制转换为float*,将计算结果转为int


#include<stdio.h>
#include<stdlib.h>

int main()

	float arr[] = 9.22,9.21,8.99,8.21,0,8.89,10.2,7.8,6.3,10.1,2.1 ;
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), compare);
	int a = 0;
	for (a = 0; a < sz; a++)
	
		printf("%f\\n", arr[a]);
	
	return 0;


数组元素为字符时比较函数定义:

在c语言中,字符和整数是相通的,所以它们的比较函数差不多:

int  compare(const void *e1,const void *e2)


	return  (int)(*(char*)e1 - *(char*)e2);



#include<stdlib.h>

int main()

	char arr[] = 'e','f','c','a','b';
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), compare);
	int a = 0;
	for (a = 0; a < sz; a++)
	
		printf("%c\\n", arr[a]);
	
	return 0;

结构体数据比较函数定义:

结构体其实和数组一样:

struct stu//创建结构体变量

	char name[20] ;
	int age;
;
int compare(const void*e1, const void *e2)

	return  strcmp((*(((struct stu*)e1)->name) , *(((struct stu*)e2)->name)));//将指针强制转换为结构体指针



int main()

	struct stu s1[3] =    "zhangsan" ,  20  ,   "lisi" ,  10  ,   "abo" ,  15   ;
	//s1是一个数组,数组有3个元素,每个元素都是一个结构体。
	int sz = sizeof(s1) / sizeof(s1[0]);
	qsort(s1, sz, sizeof(s1[0]), compare);
	int a = 0;
	for (a = 0; a < sz; a++)
	
		printf("%s\\n", (s1+a)->name);//打印结构体
	
	return 0;


``

博主不才,如有错误请及时指出,如果有想深入了解qsort函数的朋友 点击链接  [qsort函数源码分析](https://blog.csdn.net/nuptxxp/article/details/6961030) 相信会找到你想要的。

加油csdn的小伙伴,让我们一起努力,向大厂前进!!!

以上是关于qsort函数实现对任意数据的排序的主要内容,如果未能解决你的问题,请参考以下文章

c语言重要库函数解读 和模拟实现————Qsort

怎么样才能做到对多种数据类型排序?C语言快速排序——qsort函数及其模拟实现

C语言之qsort函数进行排序

CGO实战-封装qsort函数

CGO实战-封装qsort函数

4.19 使用qsort对结构体数组进行排序,实现对结构的体一级排序和二级排序,进一步了解qsort的原理