qsort函数的使用方法

一.qsort介绍与用法

快速排序函数qsort可以以O(nlogn)的时间复杂度完成排序,并且可以对所有数据类型进行排序,在使用时要引用头文件<stdlib.h>.

qsort的声明是这样的:

void qsort(void* base,size_t num,size_t size,int(*compar)(const void*,const void*))

 base是待排序首元素的地址,num是待排序的数据个数,size是待排序数据的大小(字节),最后一个参数是一个函数指针,实现的功能是比较两个数据的大小,需要由我们自己实现。

下面介绍compar函数的写法:

从声明中可以看出,compar函数的参数有两个,分别是待排序的两个数据e1、e2,返回一个整形(返回正值表示e1大于e2,返回0表示相等,返回负值表示e1小于e2)。

我们以字符串和整形比较为例:

1.整形的比较

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

 2.字符串的比较

int compar(const void* e1, const void* e2)
{
    return strcmp((char*)e1, (char*)e2);
}

 这里要注意,不能直接指针e1、e2进行解引用操作,因为它们的类型都是void*型,我们要先进行强制类型转换,如果比较的内容是整形,就转化为(int*),如果比较的内容是字符或字符串,就转化为(char*)。

二.qsort的实际使用 

接下来我们看几个qsort的常见应用:

1.对结构体排序

要求:制作一个OJ排行榜,分数越高的排名越靠前,分数相同时罚时少的排名靠前。

分析:创建一个结构体变量来存储每个学生的姓名、分数、罚时,以分数为第一关键字降序排序,以罚时为第二关键字降序排序。

具体代码如下:

struct Stu
{
	char name[10];
	int score;
	int time;
};

int cmp(const void* e1, const void* e2)
{
	struct Stu* s1 = (struct Stu*)e1;
	struct Stu* s2 = (struct Stu*)e2;
	if (s1->score != s2->score)
		return s2->score - s1->score;
	else
		return s1->time - s2->time;
}

int main()
{
	struct Stu s[4] = { {"Maria", 10, 3},{"Alice", 20, 3},{"Julia", 15,3}, {"Jimmy", 15, 2}};
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s,sz,sizeof(s[0]), cmp);
	for (int i = 0; i < sz; i++)
	{
		printf("name:%s  score:%d  time:%ds\n", s[i].name,s[i].score,s[i].time);
	}
	return 0;
}

 2.对二维数组进行排序

        对二维数组进行排序时分两种情况,第一种情况是二维数组是动态开辟的(如果不了解动态内存管理可以看这篇文章: 动态内存管理(C语言)_rao_xuanxuan的博客-CSDN博客),一般形式如下:

//动态开辟一个二行三列的数组arr
int** arr = (int**)malloc(sizeof(int*) * 2 );
*arr[0] = (int*)malloc(sizeof(int) * 3);
*arr[1] = (int*)malloc(sizeof(int) * 3);

        这时候数组名arr是一个二级指针,cmp写法如下:

int cmp(const void* e1, const void* e2){
    int** a = (int**)e1;
    int** b = (int**)e2;
    //注意[]的优先级比*高,要加括号
    return (*a)[0] - (*b)[0];
}

        而当arr不是由malloc等动态开辟时,也就是形如:arr[2][3]这样的情况下,数组名arr严格来说并不是二级指针,而是一个指向一维数组的指针,即数组指针,cmp写法如下:

int cmp(const void* e1, const void* e2){
    return ((int*)e1)[0] - ((int*)e2)[0];
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ChenxuanRao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值