模拟qsort函数功能实现一个通用的冒泡排序(可用于多种类型数组的元素排序)

首先我们了解一下qsort函数的功能

之前的冒泡排序太过局限,我们仿qsort写一个可对任意类型的数组进行排序的冒泡排序

目录

一、了解qsort函数

二、模拟实现

1.main函数调用

2.qsort函数模拟实现

3.比较函数cmp的实现

4.交换函数的实现

5.全部代码

6.测试结果

三、总结


一、了解qsort函数

qort函数是对数组元素进行快速排序的函数

void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );

可以看到qsort函数共有4个参数:

  1. void *base  数组起始地址(可直接用数组名来传参),用指针来接收,这里用的void类型的指针使得这个qsort函数可以接收不同类型数组的首元素地址,使qsort函数能用于多种类型数组的元素排序
  2. size_t num  数组的长度
  3.  size_t width  数组元素的大小(以字节为单位)     (因为第一个和第二个参数即数组元素大小和数组长度不可能为负数,所以这里用的是size_t无符号整型,我们模拟的时候用int类型也完全没有问题,而且int类型和size_t类型相比,int类型有时候可以避免掉一些不必要的歧义以及错误的产生)
  4. int (__cdecl *compare )(const void *elem1, const void *elem2 ),为方便理解,我们将它简化如下,int ( *compare )(const void *elem1, const void *elem2 ),可以看出这其实就是一个函数指针,该指针所指向的函数有两个空类型的指针作为参数,返回值为int类型。                     第4个参数函数指针所指向的函数其实就是qsort函数需要我们给它提供一种比较的方法,不同类型的数组排序方法不同,所以这个比较函数是需要我们自己来写的。比较函数比较完两个元素后返回一个值给qsort,第一个数小于第二个数返回负数,等于返回0,大于返回正数

注意

  1. qsort函数无返回值,只是进行数组元素的排序
  2. qsort函数默认按从小到大排序,若要从大到小,可更改自己所写的比较函数的返回值正负
  3. 因为要广泛适用于多种类型,所以自己所写的比较函数的两个参数均为void类型

二、模拟实现

1.main函数调用

int main()
{
	int arr[] = { 10,9,8,7,6,5,4,3,2,1 };     //定义整型数组并初始化
	int sz = sizeof(arr) / sizeof(arr[0]);    //计算数组长度
	int i = 0;
	bubble_sort(arr, sz, sizeof(arr[0]), cmp);    //模拟qsort函数实现冒泡排序,bubble_sort传 
                                                     //过去4个参数,cmp为比较函数
	for (i = 0; i < sz; i++)                   
	{
		printf("%d ", arr[i]);                     //排序完后对数组进行打印,验证排序是否成功
	}
}

下面进行qsort函数功能的模拟实现,我们以整型数组为例

2.qsort函数模拟实现

冒泡排序函数bubble_sort如下

void bubble_sort(void* arr, int sz, int width, int(*cmp)(void* e1, void* e2))

       bubble_sort函数中我们接收到了数组首元素地址,数组长度,以及每个数组的大小,比较函数均可以用,在进行冒泡排序时,我们应该清楚在符合什么条件的情况下要将两个元素交换位置,以达到排序的目的。

        我们拿到首元素的地址arr,即可以通过地址访问数组,arr+1表示第二个元素的地址,这里将arr和arr+1传给cmp比较函数并接收它的返回值决定要不要交换即可,但是这里的arr为void*类型,不能进行arr+1的操作,所以我们对它进行强制类型转换,char*(arr),而我们要将整个数组的元素都要进行传参比较,所以char*(arr)和char*(arr)+1比较局限,将width这个参数用上,则相邻的两个元素地址可以写成(char*)arr + (j * width), (char*)arr + (j + 1) * width),将其传给cmp函数比较即可

整个bubble_sort函数实现如下

void bubble_sort(void* arr, int sz, int width, int(*cmp)(void* e1, void* e2))
{
	int i = 0;
	int j = 0;
	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)
			{
				//符合条件进行交换
				swap((char*)arr + (j * width), (char*)arr + (j + 1) * width,width);
			}
		}
	}
}

3.比较函数cmp的实现

这里是整形数组,我们进行比较时,只需要将两数相减作为返回值即可。cmp的两个参数为void*类型,不能解引用,所以我们对它需要进行强制类型转换后解引用

代码实现如下:

int cmp(void* e1, void* e2)   //所选择的比较方法
{
	return *((int*)e1) - *((int*)e2);
}

4.交换函数的实现

写交换函数,在cmp的返回值满足交换条件时,调用交换函数来交换两个元素

交换函数需要width(数组单个元素的大小)用作for语句的边界,因为这里我们交换时一个字节一个字节进行交swap函数的前两个参数为char*类型,所以可以一个字符一个字符进行交换,但到底交换几对字符,不同类型数组都不一样,所以再传一个数组单个元素的大小给swap函数。

void swap(char* p1, char* p2, int width)   //实现数组元素的交换
{
	int t = 0;
	int i = 0;
	for (i = 0; i < width; i++)
	{
		t = *p1;
		*p1 = *p2;
		*p2 = t;
		p1++;
		p2++;
	}
}

到这里,整个qsort函数的功能模拟完成

5.全部代码

#include<stdio.h>

//仿qsort函数重写冒泡排序
int cmp(void* e1, void* e2)   //所选择的比较方法
{
	return *((int*)e1) - *((int*)e2);
}
void swap(char* p1, char* p2, int width)   //实现数组元素的交换
{
	int t = 0;
	int i = 0;
	for (i = 0; i < width; i++)
	{
		t = *p1;
		*p1 = *p2;
		*p2 = t;
		p1++;
		p2++;
	}
}
void bubble_sort(void* arr, int sz, int width, int(*cmp)(void* e1, void* e2))
{
	int i = 0;
	int j = 0;
	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)
			{
				//符合条件进行交换
				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 };     //定义整型数组并初始化
	int sz = sizeof(arr) / sizeof(arr[0]);    //计算数组长度
	int i = 0;
	bubble_sort(arr, sz, sizeof(arr[0]), cmp);    //模拟qsort函数实现冒泡排序
	for (i = 0; i < sz; i++)                   
	{
		printf("%d ", arr[i]);                     //排序完后对数组进行打印,验证排序是否成功
	}
}

6.测试结果

成功实现排序

三、总结

今天我们学习了qsort函数,了解到了qsort函数中的4个不同参数的意义及作用,并以整型数组为例模仿qsort函数写出了适用于任意类型数组排序的bubble_sort函数,自己也可以用这个bubble_sort函数对字符数组,结构体数组等进行排序,排序方法cmp不同的类型都可能不同,需要自己根据具体情况去写比较函数cmp。关于这种方法你学会了吗?

        欢迎关注,学习编程请关注 Go-ly,让我们一起将编程进行到底!

        更多干货等你哦!

 

 

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_错错错

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

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

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

打赏作者

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

抵扣说明:

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

余额充值