带你纯C冒泡实现可排序任意类型的函数-- my_qsort

qsort是一个库函数,本文内容就是模拟实现qsort

思路:本质还是排序!

排序有很多种办法,我选了冒泡排序来实现

排序的基本逻辑也和冒泡一样

不一样的点:交换数据的函数和比较函数

这也是为什么可以实现任意类型的排序

交换数据:

因为不清楚交换数据的类型,所以采用一个字节一个字节进行交换

我们怎么知道要交换几个字节?用sizeof算元素大小呗

比较函数(cmp函数):

这个函数是自定义的,需要根据类型的不同具体写出不同的函数

比如:返回值大于0对应大于的情况

          返回值小于0对应小于的情况

          返回值等于0对应等于的情况

如果上述规则对应升序,那么反过来就对应降序(把cmp函数的两个指针交换一下)

为什么my_qsort() 有四个参数?

(qsort也有四个参数)

第一个参数决定了排序的起始地址,第二和第三个参数决定了排序范围,第四个参数决定了比较的方式和比较到底是升序还是降序


int cmp_int(const void* e1, const void*e2)
{//以排序整型为例的cmp函数
	return *((int*)e1) - *((int*)e2);
}

void my_swap(char* e1, char *e2 ,int width)//需要width,cmp函数是需要自己构造,所以不用传width
//不需要再定义为void  已经确定逐字节交换
{
	for (int i = 0; i < width; i++)
	{
		char tmp = *e1;
		*e1 = *e2;
		*e2 = tmp;
		e1++;
		e2++;
	}
}
void my_qsort(void* base,int sz,int width,int (*cmp)(const void*e1,const void* e2))
{
	for (int i = 0; i < sz; i++)
	{
		for (int j = 0; j < sz - 1-i; j++)
		{
			if (cmp((char*)base + j*width, (char*)base + (j + 1)*width)>0)
			{
				my_swap((char*)base + j*width, (char*)base + (j + 1)*width,width);
			}
		}
	}
}

以一道例题和一个乱序的数组作为测试用例

例题:一张成绩单上有成绩和名字,一个成绩对应一个名字,现在要求对成绩单进行排序,如何实现?

struct student
{
	char name[50];
	int grade;
};
int cmp_int(const void* e1, const void*e2)
{
	return *((int*)e1) - *((int*)e2);
}
int cmp_stu_int(const void*e1, const void* e2)
{
	return ((student*)e1)->grade - ((student*)e2)->grade;
}
int cmp_name(const void* e1, const void* e2)
{
	return strcmp((char*)e1, (char*)e2);
}
void my_swap(char* e1, char *e2 ,int width)
{
//需要width,cmp函数是需要自己构造,所以不用传width
//不需要再定义为void  已经确定逐字节交换,也即确定字符型
	for (int i = 0; i < width; i++)
	{
		char tmp = *e1;
		*e1 = *e2;
		*e2 = tmp;
		e1++;
		e2++;
	}
}
void my_qsort(void* base,int sz,int width,int (*cmp)(const void*e1,const void* e2))
{
	for (int i = 0; i < sz; i++)
	{
		for (int j = 0; j < sz - 1-i; j++)
		{
			if (cmp((char*)base + j*width, (char*)base + (j + 1)*width)>0)//比较
			{
				my_swap((char*)base + j*width, (char*)base + (j + 1)*width,width);//交换
			}
		}
	}
}

void pr1(int* arr,int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *(arr + i));
	}
	printf("\n");
}
void test1()
{
	int arr[] = { 0, 9, 8, 2, 6, 5, 3, 4, 1, 7 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	my_qsort(arr, sz, sizeof(arr[0]), cmp_int);
	pr1(arr, sz);
}
void pr2(student* ans,int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%s  %d\n", (ans + i)->name, (ans + i)->grade);
	}
	printf("\n");
}
void test2()
{
	student s[] = { { "red", 50 }, { "yellow", 40 }, { "blue", 80 } };
	int sz = sizeof(s) / sizeof(s[0]);
	//my_qsort(s, sz, sizeof(s[0]), cmp_name);
	my_qsort(s, sz, sizeof(s[0]), cmp_stu_int);
	pr2(s,sz);

}

int main()
{
	test1();
	test2();
	return 0;
}

如果想试试上述函数的效果如何?可以拷贝到自己编译器试试哦!

总结

排序任何类型的本质还是排序,不过是数据的交换和比较方式不同而已

针对这两个问题:

数据的交换问题:逐字节交换

比较方式的问题:结合返回值来自己构造规则

只要会构造cmp函数就能使用qsort函数了,要是还会冒泡和数据交换那你自己就可以写出自己的qsort实现任何类型的排序了

-------

如果有启发的话,留个赞再走吧,这对我帮助很大!

不点?

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

喜欢乙醇的四氯化碳

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

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

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

打赏作者

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

抵扣说明:

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

余额充值