C语言-指针进阶-qsort函数的学习与模拟实现(9.3)

目录

思维导图:

回调函数

qsort函数介绍

模拟实现qsort

写在最后:


思维导图:

回调函数

什么是回调函数?

回调函数是一个通过函数指针调用的函数。

将一个函数指针作为参数传递给一个函数,当这个指针被用来调用所指向函数时,

我们就将此称为回调函数。

在举例之前,我们先学习一个C语言的库函数qsort。        

qsort函数介绍

qsort函数是一个排序函数,可以帮助我们排序。

我们为什么要学习这样一个函数呢?

我们对一个整形数组进行排序:

例:

#include <stdio.h>

void print(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

void bubble_sort(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}

void test()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);//冒泡排序
	print(arr, sz);//打印
}

int main()
{
	test();//分装函数
	return 0;
}

输出:

输出:0 1 2 3 4 5 6 7 8 9

但是如果我们想对一个结构体进行排序,冒泡排序就承担不了这个任务了,

(不止结构体,像浮点数啊,字符数组啊,冒泡排序都无法工作)

这个时候,我们就能使用qsort函数帮我们排序。

我们可以通过cplusplus学习一下这个函数:

通过阅读介绍,我们得知qsort的功能:

对数组中由指针指向的元素进行排序,根据每个元素字节长度,使用函数确定顺序。

此函数使用的快速排序算法通过调用指定的函数来比较元素,并将指向它们的指针作为参数。

该函数不返回任何值,但通过重新排序数组的元素来修改指向的数组的内容。

以及使用该函数需要传递的参数:

int main()
{

	void qsort(void* base, size_t num, size_t size,
		int (*compar)(const void*, const void*));
	//一个指针,两个无符号整数,一个函数指针

	return 0;
}

 这个库函数需要调用的头文件是:<stdlib.h>

以及各个参数的不同意思:

#include <stdio.h>

int main()
{

	void qsort(void* base, 
		size_t num, 
		size_t size,
		int (*compar)(const void*, const void*));
	//void*base是指向要排序的数组的第一个对象的指针,转换为void*类型
	//size_t num是数组中的元素数
	//size_t size是数组中每个元素的大小(以字节为单位)
	//int (*compar)(const void*, const void*))是指向比较两个元素的函数的指针

	return 0;
}

 这样,我们就能使用qsort函数帮助我们排序了:

例:

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

struct Stu
{
	char name[20];
	int age;
};

int cmp_stu_by_age(const void* e1, const void* e2)
{
	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
	//如果e1 > e2则返回>O的数
	//如果e1 = e2则返回0
	//如果e1 < e2则返回<0的数
}

void print(struct Stu* s, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d岁\n", (&s[i])->name,(&s[i])->age);
	}
}

void test()
{
	struct Stu s[3] = { {"张三",20}, {"李四", 50}, {"王五", 33} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);//排序
	print(s, sz);//打印函数
}

int main()
{
	test();//分装函数
	return 0;
}

输出:

输出:
张三 20岁
王五 33岁
李四 50岁

利用qsort函数,我们成功给结构体排序了。

模拟实现qsort

在模拟实现qsort时,我们就要用到回调函数的思想:

例:

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

int cmp_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
	//如果e1 > e2则返回>O的数
	//如果e1 = e2则返回0
	//如果e1 < e2则返回<0的数
}

//通过交换每个字节的形式,以达成交换两个数的值的目的
void Swap(char* buf1, char* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}
                                                      //这里将cmp_int函数的指针传参
void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* e1, const void* e2))
{
	//趟数
	size_t i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		//一趟冒泡排序的过程
		size_t j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{       //这里运用了回调函数,在冒泡排序函数里调用cmp_int函数,并判断
			    //这里判断函数返回的值大于零就进入语句,排序后是升序数组
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				//交换
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}

void print(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

void test()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
	print(arr, sz);//打印函数
}

int main()
{
	test();//分装函数
	return 0;
}

输出:

输出:0 1 2 3 4 5 6 7 8 9

再用它来排序一下结构体数组也是可以的:

例:

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

struct Stu
{
	char name[20];
	int age;
};

int cmp_stu_by_age(const void* e1, const void* e2)
{
	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
	//如果e1 > e2则返回>O的数
	//如果e1 = e2则返回0
	//如果e1 < e2则返回<0的数
}

//通过交换每个字节的形式,以达成交换两个数的值的目的
void Swap(char* buf1, char* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}
                                                      //这里将cmp_int函数的指针传参
void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* e1, const void* e2))
{
	//趟数
	size_t i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		//一趟冒泡排序的过程
		size_t j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{       //这里运用了回调函数,在冒泡排序函数里调用cmp_int函数,并判断
			    //这里判断函数返回的值大于零就进入语句,排序后是升序数组
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				//交换
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}

void print(struct Stu* s, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d岁\n", (&s[i])->name,(&s[i])->age);
	}
}

void test()
{
	struct Stu s[3] = { {"张三",20}, {"李四", 50}, {"王五", 33} };
	int sz = sizeof(s) / sizeof(s[0]);
	bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_age);
	print(s, sz);//打印函数
}

int main()
{
	test();//分装函数
	return 0;
}

输出:

输出:
张三 20岁
王五 33岁
李四 50岁

写在最后:

以上就是本篇文章的内容了,感谢你的阅读。

如果喜欢本文的话,欢迎点赞和评论,写下你的见解。

如果想和我一起学习编程,不妨点个关注,我们一起学习,一同成长。

之后我还会输出更多高质量内容,欢迎收看。

  • 39
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 56
    评论
评论 56
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

戊子仲秋

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

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

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

打赏作者

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

抵扣说明:

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

余额充值