基于冒泡排序实现任意类型的排序

这是最简单的冒泡排序写法,但是我们好像发现这种写法只能排序固定的类型,如果要写一个可以排任意类型的冒泡排序,我们要怎么写呢?

int main()
{
	int arr[] = { 1,2,3,4,5 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0; i < sz -1; i++)
	{
		for (int j = 0; j < sz - i - 1; j++)
		{
			if (arr[j] < arr[j + 1])//降序
			{
				//交换
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
	return 0;
}

这时候我们就要使用回调函数的写法了。回调函数可以让我们无需关心数据的类型,只做排序的工作即可。

冒泡排序的思想还是和原来一样,关键是如何进行前后两个元素的比较。我们知道两个不同类型的数据是不能一起比较的,字符串之间也不能用大于小于等于来比较,因此我们要参考qsort的思想,传入一个比较函数。

比较函数的写法:
https://blog.csdn.net/m0_51641706/article/details/120050285?spm=1001.2014.3001.5501

void Bsort(void* base, size_t num, size_t width, int(*cmp)(const void*, const void*))
{
	for (size_t i = 0; i < num - 1; i++)
	{
		for (size_t j = 0; j < num - i - 1; j++)
		{
			if ((cmp((char*)base+j*width,(char*)base+(j+1)*width))>0)
			//base是void*,无法进行运算。因此强制转换成char*
			,加1*width即跳过一个对应的类型
			{
				swap((char*)base + j * width, (char*)base + (j + 1) * width,width);
			}
		}
	}
}

上面这段代码的难点是cmp函数里面的参数。我们知道,冒泡排序里面cmp传入的是前后两个元素,即第j个和第j+1个元素。

转换成char*的原因是char*的精细度最高,若转换成int*,就无法比较char类型了
在这里插入图片描述
接下来是交换函数

void swap(char* e1, char* e2,int width)
{
	for (int i = 0; i < width; i++)
	{
		char tmp = *e1;
		*e1 = *e2;
		*e2 = tmp;
		e1++; 
		e2++;
	}
}

我们可以把两个元素对应的补码的每一个字节进行交换。
这种方法可以记住,是通用的。
在这里插入图片描述

完整的代码

void swap(char* e1, char* e2,int width)
{
	for (int i = 0; i < width; i++)
	{
		char tmp = *e1;
		*e1 = *e2;
		*e2 = tmp;
		e1++; 
		e2++;
	}
}
void Bsort(void* base, size_t num, size_t width, int(*cmp)(const void*, const void*))
{
	for (size_t i = 0; i < num - 1; i++)
	{
		for (size_t j = 0; j < num - i - 1; j++)
		{
			if ((cmp((char*)base+j*width,(char*)base+(j+1)*width))>0)//base是void*,无法进行运算。因此强制转换成char*,加1*width即跳过一个对应的类型
			{
				swap((char*)base + j * width, (char*)base + (j + 1) * width,width);
			}
		}
	}
}

附几种常用的比较函数:

int cmp_int(const void* e1, const void* e2)//整型
{
	return *(int*)e1 - *(int*)e2;
}
int cmp_str(const void* e1, const void* e2)//字符指针数组(比较字符串
{
	return strcmp(*(char**)e1, *(char**)e2);
}
int cmp_stu_name(const void* e1, const void* e2)//比较结构体的成员
{
	return strcmp(((stu*)e1)->name, ((stu*)e2)->name);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值