qsort函数大改造

 qsort是<stdlib.h>库中快速排序算法的函数,其排序范围不单单为整形,也包括字符串,浮点型等数据。使用qsort需要传入数据地址,元素的个数及其宽度,和我们自定义的比较函数的地址。

冒泡排序通过两层循环,对数据进行两两比较并交换,但其只能排序整型。我们需要冒泡排序的循环比较逻辑,加上自定义的比较函数和交换函数,来改造出功能与qsort相似的my_sort函数。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>//使用冒泡排序的逻辑实现qsort函数;
int my_int_cmp(const void* e1, const void* e2)//比较函数
{
	return *((int*)e1)- *((int*)e2);//需要将空类型的指针强制转换类型为我们需要的类型
}//对于整形来说,直接返回相减值,若返回值>0,则说明需要交换


void swap(char* j, char* J, int width)//交换函数(回调函数)
{
	int i;
	for (i = 0; i < width; i++)//两两交换第一个字节,直到第width个字节
	{
		char tmp = *j;
		*j = *J;
		*J = tmp;
		j++;
		J++;
	}
}


void my_sort(void* arr, int sz, int width, int(*cmp)(const void* e1, const void* e2))//(注意)使用空类型接收数据地址,使用函数指针接收函数地址
{
	int i, j;
	for (i = 0; i < sz - 1; i++)//趟数
	{
		for (j = 0; j < sz - 1 - i; j++)//每一趟比较并交换元素的次数
		{
			if (cmp((char*)arr + j * width, (char*)arr + (j + 1) * width) > 0.00)//进行比较,满足条件进行交换
			{
				swap((char*)arr + j * width, (char*)arr + (j + 1) * width, width);//传入需交换的两个元素地址和宽度
			}
		}
	}
}



int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	my_sort(arr, sz, sizeof(arr[0]), my_int_cmp);//输入和qsort相同类型的参数:数据起始地址,元素个数,宽度,回调函数的地址
	int i;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

进入my_sort函数,借助两层冒泡循环,我们可以对数据两两比较。因为各类型数据的差异性,需要定义一个比较函数:以整型为例,假设需要排序的数据为一个整型数组。需要明确的是,传入比较函数my_int_cmp的地址用空类型指针接收,返回类型为整型。将传入的地址强制为整形并解引用就得到了我们需要比较的数据,直接返回两整型数据的差值,若差值>0,则进入条件语句进行交换。

void swap(char* j, char* J, int width)//交换函数(回调函数)
{
	int i;
	for (i = 0; i < width; i++)//两两交换第一个字节,直到第width个字节
	{
		char tmp = *j;
		*j = *J;
		*J = tmp;
		j++;
		J++;
	}
}

明确需要交换的数据后,便进入swap函数进行交换,传入两数据的地址为(char*)类型,解引用访问的权限为1个字节,这就需要我们传入宽度,并借助循环,将数据的字节两两进行交换。因为无论什么类型的数据都以字节为单位储存,使这种交换的方式具有通用性,也就是说只要传入地址和宽度,便可以通过该函数来交换,实现了qsort函数的交换功能。

我们再以浮点型为例:

float my_float_cmp(const void* e1, const void* e2)//比较函数
{
	return *((float*)e1) - *((float*)e2);//需要将空类型的指针强制转换类型为浮点型
}//对于浮点型来说,直接返回相减值,若返回值>0,则说明需要交换
//返回类型需要改为float避免数据丢失

我们只需要改变比较函数,就能实现多种类型数据的排序。

这种排序默认为升序,若把指针e1和e2交换或改变判断条件,则可以改为降序。

通过这次改造可以说明函数指针的重要性,将my_soort函数中比较和交换分开来分别交给swap和my_cmp,这使得回调函数起到一个外包的作用,将函数的某一功能外包给另一函数去做,避免了函数的冗杂,提高了可读性。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值