利用qsort的相关知识改进冒泡排序


在这里插入图片描述

前言

本篇是通过qsort的学习,改进冒泡排序,如果有不懂qsort的可以去我前面的文章看看
回调函数与用qsort排各种类型的数据

一、冒泡排序

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

我们能看到经典的冒泡排序需要我们指定一个排序类型,不够通用,不能封装成一个函数

二、qsort函数

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


我们可以看到qsort函数之所以可以封装成为函数,是因为其的通用性,void*类型的指针就决定了其的通用性


三 、冒泡排序的改进

通过对qsort的研究,我们可以参考qsort对其进行修改
(1)我们可以对冒泡排序的形参就行修改
void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* e1, const void* e2))
(2)但是我们需要保持冒泡排序的特征,所以趟数是不会变的
(3)我们使用了void类型的指针,那就意味着我们需要对于swap进行修改,不然会造成数据丢失
(4)我们使用了void
函数,我们通过步长移动的时候我们怎么控制其的移动呢,我们得到了width,那么我们是不是可以强制转换数据为char类型,这样我们移动width是不是就可以精准的移动到下一个元素的首字节上去

其实冒泡排序的修改最关键的就是对于swap的修改,怎么修改才能不造成数据丢失呢?我们想想我们要width是想干嘛,width是告诉我们我们传的数据的字节数,我们通过数组的首地址和数组的每个元素的字节大小是不是就可以知道数据的每个元素,同时我们甚至可以修改每个字节,其实这里我们也可以看出指针的好处(哈哈哈,题外话),既然我们知道了每个字节的位置,那么我们是不是可以通过修改每个元素的每个字节,从而修改这个数据
举个例子一个int 类型的数据强制转换成为char类型的数据,我们将int的4个字节全部完整的赋值到另外一个int 数据上去,是不是就不会造成数据丢失了呢,通过这种思路我们可以将swap修改成

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++;
	}
}

至此,我们就将冒泡排序修改完成了

四 、最终代码

void Swap(char* buf1, char* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)//这里的swap交换的是每个元素的每个字节
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}
int cmp_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}
//改造冒泡排序函数,使得这个函数可以排序任意指定的数组
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++)
		{
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
			{
				//交换
				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
			}
		}
	}
}
  • 25
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 21
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Ruiren.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值