C语言-qosrt函数—秩序大师

1、qsort()的作用

在我们的日常生活中,排序无处不在。想象一下,当你整理书架时,会按照书籍的类别、作者或者大小进行排列,让你的阅读空间更加整洁有序。又比如,在超市的货架上,商品通常也是按照一定的规则进行排序,方便顾客快速找到所需物品。在学校里,老师可能会根据学生的成绩进行排名,以了解学生的学习情况。

而在计算机编程的世界里,同样需要对数据进行高效的排序。这时,qsort 函数就如同一位强大的秩序之师,挺身而出。qsort 函数是 C 语言标准库中的快速排序函数它能够快速而有效地对各种数据进行排序。无论是简单的整数数组,还是复杂的结构体数组,qsort 函数都能轻松应对。它以其高效的性能和灵活的用法,成为了程序员们在处理数据排序问题时的得力助手。

说了这么多,接下来我们也该来见一见这位秩序大师的庐山真面目了!

2、qsort函数的基本信息

在cplusplus(C语言函数查询网站)上,我们可以看到qsort函数的函数原型

eb4f368f71f443cba37f527e5159ca93.png

qsort函数是有4个变量的,分别是base,num,size,comper

他们的类型分别是void*;size_t;size_t;int(*)(const void*,const void*);

cplusplus上对这四个变量的解释:(下图为机翻,因此可能会有些不准确)

33016d7eece44e29a4237b64a4727c2e.png

对上面的参数解释的理解:

  • base:base中存放的是待排序数组的第一个元素的地址
  • num:num存放的是base指向的数组的元素个数
  • size:size是base指向的数组中一个元素的长度(以字节为单位)。
  • comper:函数指针—指向了一个比较函数,这个比较函数用来比较数组中的两个元素的大小

int(*)(const void* e1,const void* e2)中:

如果e1指向的元素大于e2指向的元素,那么函数返回>0的数字

如果e1指向的元素等于e2指向的元素,那么函数返回0

如果e1指向的元素小于e2指向的元素,那么函数返回<0的数字

3、qsort函数变量的详细介绍

1.void*base

base中存放的是待排序数组的第一个元素的地址

关于base的作用就是为了寻找到待排序的数组的地址,这里为什么使用void*指针呢?

void*指针,可以接收任意类型变量的地址。所以,这里我们使用void*指针来修饰base的目的是为了能够接收任意类型的数组。微软公司在创造这个函数的时候,是不知道使用者将要排序什么类型的数组,所以需要使用void*来修饰。

2.size_t num

num存放的是base指向的数组的元素个数

不管是冒泡排序,还是快速排序,我们都需要知道所要排序的元素个数,这个参数很好理解。

3.size_t size

size:size是base指向的数组中一个元素的长度(以字节为单位)

可能有些人很疑惑,为什么还需要知道数组中一个元素的长度呢?

这是由于base的数据类型是void*

如果我们是int*的话,向后看到的就是整型数组,如果我们是char*的话,向后看到的就是字符数组。但是我们使用的是void*指针,所以我们不知道数组中的元素的具体类型,所以我们需要传递

数组中一个元素的长度,如果排序的是整型的话,一个元素长度是4个字节,如果排序的字符类型的话,一个元素长度是1个字节。

如果没有size参数,给你一个空间,访问十个元素,那么访问一个元素的长度是多大呢?访问十个元素所要占的长度是多少呢?

c431f53a728f4d72a6c4648a9e1a883b.png

这就像是在路边询问路线,您需要到达一个地方。有人告诉您向前走十步就能到达,但他们没有说明一步应该走多远。或许他们每步迈的幅度较大,而您迈的幅度较小。因此,当您走了十步之后,可能会发现并没有到达目的地。

我们既需要知道访问多少个元素,也需要知道访问一个元素的长度才能够更加准确的访问空间。

4.int(*comper)(const void*,const void*)

先来分析一下int(*)(const void*,const void*)

首先,该参数是一个函数指针,它指向一个有两个无类型指针作为参数的函数,并且该函数的返回值是int类型的。

该函数指针的作用是将两个无类型指针指向的参数进行比较,如果参数1小于参数2返回小于0的整数,如果参数1等于参数2,返回0,如果参数1大于参数2,返回大于0的整数。

comper()函数的作用仅仅是比较两个参数的大小,并且通过返回值来告诉我们比较的结果,但是所比较的两个数是不能修改的。使用const修饰。

注意:使用qsort函数排序默认是升序

当我们得到的返回值>0的值时,qsort函数将会将这两个数字交换,当得到的返回值<0的值时,qsort函数将不会对其进行交换。

4、使用qsort函数排序整型数组,结构体数组

当我们了解了qsort函数的一些基础知识后,可以使用qsort函数来完成一些数据的排序;

4.1 使用qsort函数来排序整型数组:

#include <stdio.h>
#include <stdlib.h>
int cmp_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;//通过相减来直接获得返回值的大小
}
void print_arr(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
void test1()
{
	int arr[10] = { 3,2,5,7,4,9,0,1,8,6 };//所排数组
	int sz = sizeof(arr) / sizeof(arr[0]);//元素个数
	qsort(arr, sz, sizeof(arr[0]), cmp_int);//qsort函数参数的传递
	print_arr(arr, sz);
}
int main()
{
	test1();
}

return *(int*)e1 - *(int*)e2这里通过相减可以直接获得返回值,如果e1>e2,返回>0的数,如果e1<e2, 返回<0的数,因此,使用qsort函数排序默认为升序,如果想要排逆序,只需要交换e1和e2的位置即可。

4.2 使用qsort函数来排序结构体数组:

//创建结构体变量
struct Stu
{
	char name[20];//人名
	int age;//年龄
};
void test2()
{
	struct Stu s[3] = { {"zhangsan",18},{"lisi",25},{"wangwu",20} };//创建结构体数组
	int sz = sizeof(s) / sizeof(s[0]);//获得数组元素个数
	qsort(s, sz, sizeof(s[0]), cmp_stu);

}
int main()
{
	test2();
}

 当开始调用函数cmp_stu来比较结构体数组时,这时候就会产生疑问,该按照什么来比较结构体大小,是按照名字字母顺序来比较?还是按照年龄来比较?

4.2.1 按照年龄来排序结构体数组:

cmp_stu_by_age(const void* e1, const void* e2)
{
	return (*(struct Stu*)e1).age - (*(struct Stu*)e2).age;
}
//e1.e2分别指向两个结构体对象

 (struct Stu*)e1这是将e1的类型强制转换为struct Stu*结构体类型。

完整代码:

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

struct Stu
{
	char name[20];
	int age;
};
cmp_stu_by_age(const void* e1, const void* e2)
{
	return (*(struct Stu*)e1).age - (*(struct Stu*)e2).age;
}
void test2()
{
	struct Stu s[3] = { {"zhangsan",18},{"lisi",25},{"wangwu",20} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);//qsort函数参数的传递
	for (int i = 0; i < 3; i++)
	{
		printf("%s,%d\n", s[i].name, s[i].age);
	}
}
int main()
{
	test2();
}

dd7bb03f9fa24a72a9abe50975f81274.png

 4.2.2 按照姓名来排序结构体数组:

在比较前,我们先了解一个函数strcmp函数,该函数的作用是用来比较字符串的大小

使用格式:strcmp(字符串1,字符串2)

如果字符串1 大于 字符串2,返回大于0的数字;

如果字符串1 小于 字符串2,返回小于0的数字;

我们知道名字是字符串,所以不能直接使用>比较,因此我们通过strcmp函数来比较大小

strcmp函数的使用需要包含头文件<string.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Stu
{
	char name[20];
	int age;
};
cmp_stu_by_name(const void* e1, const void* e2)
{
	return strcmp((*(struct Stu*)e1).name , (*(struct Stu*)e2).name);
}
void test2()
{
	struct Stu s[3] = { {"zhangsan",18},{"lisi",25},{"wangwu",20} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);//qsort函数参数的传递
	for (int i = 0; i < 3; i++)
	{
		printf("%s,%d\n", s[i].name, s[i].age);
	}
}
int main()
{
	test2();
}

 

评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值