qsort函数的简单使用

引言

① qsort 是一个库函数,头文件是 <stdlib.h>.
② qsort 是基于快速排序算法的排序函数。

一、了解qsort函数

void qsort (void* base, // 1
            size_t num, // 2 
            size_t size, // 3        
            int (*compare)(const void* a,const void* b)); // 4
            
// 1. base 表示的是数组首元素的地址,一般为数组名
// 2. num 表示的是数组中元素的个数
// 3. size 表示的数组中每个元素所占内存的字节大小
// 4. compare 表示一个函数指针,指向自定义函数的地址。也就是说,使用什么样的自定义函数,直接传过来给 qsort 调用即可。

注意事项:

① compare 参数可以这么做:我们自己进行创建的一个函数 function,然后把 function 的地址作为 qsort 的 compare 参数。(这需要理解函数指针的知识,如果不理解也没关系,直接传函数名,也可以表示函数的地址)

② 自定义函数的形参为 a 和 b,它们都是 void* 指针类型。这么设计的原因就是:待排序的数据不确定,(可能是整型、浮点型、字符…)。后期在自定义函数中,先强制转换,再解引用也可以很好地比较元素。

二、使用qsort函数对数组中的各种类型进行排序

1. 整型元素排序

#include <stdio.h>
#include <stdlib.h>
int compare(const void* a, const void* b);

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

	qsort(arr,sz, sizeof(int), compare);

	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}
int compare(const void* a, const void* b)
{
	return (*(int*) a - *(int*) b);
}

//解释  qsort(arr,sz, sizeof(int), compare);
//1. arr是数组名,表示首元素的地址

//2. sz表示数组中所有元素的个数,这里sz = 10

//3. sizeof(int)是计算数组中的每个元素是多少字节的
//经计算后是4个字节,或者写成 sizeof(arr[0])

//4. compare表示我们自己创建的一个函数
//规则就是接收两个无符号指针类型,目的在于排序任何类型的变量

//5. 解释  return (*(int*) a - *(int*) b);
//(1)将其先强制转换成int* 指针,目的是确定元素的类型为 int
//(2)再解引用,目的是通过指针找到数组中的元素
//(3)最后返回

输出结果:
输出结果

注:如果我们把a和b调换位置,那么就会进行降序操作

#include <stdio.h>
#include <stdlib.h>
int compare(const void* a, const void* b);
int main(void) 
{
	int arr[] = { 9,7,8,4,5,6,1,2,3,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);

	qsort(arr,sz, sizeof(int), compare);

	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}
int compare(const void* a, const void* b)
{
	return (*(int*) b - *(int*) a);
}

输出结果:
输出结果

2. 字符串中的字符元素排序

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int compare(const void* a, const void* b);


int main(void)
{
	char arr[] = "adgcefb";
	int len = strlen(arr);

	qsort(arr, len, sizeof(char), compare);

	printf("%s\n", arr);

	return 0;
}

int compare(const void* a, const void* b)
{
	return strcmp((char*)a, (char*)b); 
	//用strcmp比较字符串
}

//解释  qsort(arr, len, sizeof(char), compare);
//1. arr是数组名,表示首元素的地址

//2. len表示数组中待排序的字符的格式,不包括'\0'

//3. sizeof(char)是计算数组中的每个元素是多少字节的,经计算后是1个字节
//或者写成sizeof(arr[0])

//4. compare表示我们自己创建的一个函数
//规则就是接收两个无符号指针类型,目的在于排序任何类型的变量

//5. 解释  return strcmp((char*)a, (char*)b);
//(1)将其先强制转换成char* 指针,目的是确定元素的类型为 char
//(2)再解引用,目的是通过指针找到数组中的元素
//(3)最后返回

//这里用到了strlen函数和strcmp函数,不再展开讲

注:如果我们把a和b调换位置,那么仍然会进行降序操作

3. 结构体元素排序

1. 排序结构体中的字符

(1) 我们先创建一个 struct stu 类型的结构体,里面分别有名字、年龄、成绩 这三个变量
(2) 之后创建一个结构体数组,即用数组装了三个结构体变量
(3) 下面代码,目的是为了把人的名字进行排序,然后展示出来

这就好像我们大一在学校一样,用姓氏来排名
所以我创建了一个 comparebyname 函数进行排序

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int comparebyname(const void* a, const void* b);

struct stu
{
	char name[20];
	int age;
	float grade;
};


int main(void)
{
	struct stu arr[3] = { {"mingming",23,85}, {"yueyue", 20, 87},{"lili", 26, 90} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%-15s %-10d %-10f\n", arr[i].name, arr[i].age, arr[i].grade);
	}
	printf("\n");

	qsort(arr, sz, sizeof(struct stu), comparebyname);

	for (i = 0; i < sz; i++)
	{
		printf("%-15s %-10d %-10f\n", arr[i].name, arr[i].age, arr[i].grade);
	}	
	return 0;
}
int comparebyname(const void* a, const void* b)
{
	return strcmp(((struct stu*)a)->name, ((struct stu*)b)->name);
}

//解释  qsort(arr, sz, sizeof(struct stu), comparebyname)   
//1. arr是数组名,表示首元素的地址
    
//2. sz表示数组中所有元素的个数,这里sz = 3
    
//3. sizeof(struct stu)是计算数组中的每个元素是多少字节的,经计算后的值是28个字节
//(结构体内存对齐)
//这里的数组中每个元素是结构体变量,所以就是这么求得的,或者写成sizeof(arr[0])
    
//4. comparebyname表示创建一个函数,规则就是以字符串的首字符来进行排序整个数组
    
//5. return strcmp(((struct stu*)a)->name, ((struct stu*)b)->name);
//(1) (struct stu*)a 将无符号指针强制转换成一个结构体指针,目的是确定元素的类型
//(2) ((struct stu*)a)->name 访问结构体成员变量
//(3) strcmp()接收的是两个地址,也就是指针类型
//(4) 这其中的name表示的是数组首元素的地址,所以符合strcmp要求

输出结果:
字符升序
l - m - y
输出结果
同一个想法,不同逻辑
接着,我使用以年龄为排序方式

2. 排序结构体中的整型
同理,我创建了一个 comparebyage 函数

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int comparebyage(const void* a, const void* b);

struct stu
{
	char name[20];
	int age;
	float grade;
};
int main(void)
{
	struct stu arr[3] = { {"mingming",23,85}, {"yueyue", 20, 87},{"lili", 26, 90} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%-15s %-10d %-10f\n", arr[i].name, arr[i].age, arr[i].grade);
	}
	printf("\n");

	qsort(arr, sz, sizeof(struct stu), comparebyage);

	for (i = 0; i < sz; i++)
	{
		printf("%-15s %-10d %-10f\n", arr[i].name, arr[i].age, arr[i].grade);
	}
	return 0;
}
int comparebyage(const void* a, const void* b)
{
	return (*(struct stu*)a).age - (*(struct stu*)b).age;
}

//解释  qsort(arr, sz, sizeof(struct stu), comparebyage)  
//1. arr是数组名,表示首元素的地址
    
//2. sz表示数组中所有元素的个数,这里sz = 3
    
//3. sizeof(struct stu)是计算数组中的每个元素是多少字节的,经计算后的值是 28个字节
//这里的数组中每个元素是结构体变量,所以就是这么求得的,或者写成sizeof(arr[0])
    
//4. comparebyage表示创建一个函数,规则就是以成绩的大小来进行排序整个数组
    
//5. return (*(struct stu*)a).age - (*(struct stu*)b).age;
//(1) (struct stu*)a 将无符号指针强制转换成一个结构体指针,目的是确定元素的类型为 
//(2) (*(struct stu*)a).age 访问结构体成员变量
// age 是一个整型变量,所以必须解引用指针,然后访问的才是元素
//(3) 两个整型,在这qsort逻辑里面,直接用减号比较,然后返回就行了

输出结果:
数字升序
20 - 23 - 26
输出结果

总结

1. 本文意在表达如何正确、简单地使用qsort函数,并不打算介绍 qsort 函数内部算法的功能。qsort 函数是基于升序算法的,感兴趣的小伙伴可以模拟一下函数。

2. 本文没有讲到浮点类型的排序,因为它的逻辑和整形元素其实是一样的。

3. 本文用到了字符串函数,有如strlen、strcmp,这些并没有展开讲,不熟悉的小伙伴可以去MSDN,或者 cplusplus.com 去看一下,本文的 qsort函数 详细说明也可以看到介绍。

4. 本文也用到了数组、指针、结构体的一些知识,并将它们串了起来,对复习之前的C语言知识还是有亿点点帮助的,哈哈哈。

谢谢观看
Over. 谢谢观看哟~

  • 9
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

十七ing

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

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

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

打赏作者

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

抵扣说明:

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

余额充值