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的小伙伴,让我们一起努力,向大厂前进!!!
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值