冒泡排序任意类型数据

本文详细分析了C标准库中的qsort函数,探讨了如何对任意类型数据进行快速排序,并通过示例展示了如何使用qsort对浮点型数据排序。接着,实现了冒泡排序函数bubbleSort,同样适用于任意类型数据,关键在于传递正确的比较函数。文中给出了整型、浮点型和结构体类型的比较函数示例,强调了比较函数在不同数据类型排序中的重要性。
摘要由CSDN通过智能技术生成

一、分析qsort函数

  库函数qsort可以对任意的数据类型进行快速排序,只是在排序的规则上与冒泡排序有所区别,所以我们可以先对qsort函数进行分析,对实现冒泡排序任意类型会有所帮助。

  从下图可以看到qsort函数有4个参数。其中,base是待排序的一组相同类型数据的起始地址,因为是对任意类型的数据进行排序,不能用一个固定类型的指针来接收,所以选择用void*这一无具体类型指针来接收num是这一组数据的的个数;width是每个数据所占空间的大小(单位为字节);compare是一个函数指针,指向一个形参类型为两个const void*, 返回类型为int的函数,该函数实现的是两个数据的比较规则,由于要实现任意类型数据的比较,为了统一函数指针的类型,所以函数的参数类型统一用const void*

下面我们利用qsort对一组浮点型数据进行排序

#include <stdio.h>
#include <stdlib.h>
int cmp_double(const void* e1, const void e2)
{
	double ret = *(double*)e1 - *(double*)e2;
	if (ret > 0)
		return 1;
	else if (ret < 0)
		return -1;
	else
		return 0;
}
int main()
{
	double arr[] = { 1.9, 1.3, 1.1, 1.2, 1.7, 1.0, 1.5, 1.8, 1.4, 1.6 };
	int len = sizeof arr / sizeof (double);
	int(*cmp)(const void*, const void*) = cmp_double;
	qsort(arr, len, sizeof (double), cmp);
	//1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9
	return 0;
}


二、实现bubbleSort函数

  通过上面对qsort函数的大致分析,我们了解到对一组任意类型数据进行排序所需要的参数,下面我们来实现冒泡排序任意类型数据。

void bubbleSort(void* base, size_t num, size_t width,
				int(*cmp)(const void* e1, const void* e2))
{
	for (size_t i = 0; i < num - 1; i++)
	{
		int flag = 1;
		for (size_t j = 0; j < num - 1 - i; j++)
		{
			//利用width可以实现两个指针分别指向前后两个元素
			char *p1 = (char*)base + j * width, 
				 *p2 = (char*)base + (j + 1) * width;
			if (cmp(p1, p2) > 0)//p1指向的元素大于p2指向的元素
			{
				flag = 0;
				//以字节为单位交换两个数据
				for (size_t k = 0; k < width; k++)
				{
					char tmp = *p1;
					*p1 = *p2;
					*p2 = tmp;
					p1++;
					p2++;
				}
			}
		}
		if (flag)
			return;
	}
}

  不难看出,参数num让我们明确了排序的次数以及每次排序需要比较多少对元素;参数width明确了前后两个指针相隔的距离,以保证在比较函数中解引用时访问到相应空间大小的元素,以及实现以字节为单位对两个元素进行交换;参数cmp是实现排序任意类型的关键,该指针指向与排序的数据类型对应的比较函数,不同的数据类型对应不同的比较函数。

  • 整型数据对应的比较函数
int cmp_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}
  • 浮点型数据对应的比较函数
int cmp_double(const void* e1, const void* e2)
{
	double ret = *(double*)e1 - *(double*)e2;
	//防止浮点型向下取整
	if (ret > 0)
		return 1;
	else if (ret < 0)
		return -1;
	else
		return 0;
}

注意:这里之所以没有像整型比较一样返回两个元素的差值,是因为浮点型数据作为int类型返回时会向下取整(如0.1会以0进行返回)

  • 结构体类型数据对应的比较函数

以下面这一结构体类型为例,按姓名首字母对一组结构体数据进行排序。

struct Stu
{
	char name[20];
	int age;
};
int cmp_by_name(const void* e1, const void* e2)
{
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}

注意:对两个字符串进行比较,需要使用strcmp函数,将两个字符串的首字符地址传入该函数。


  以上是3种不同类型数据对应的比较函数,函数返回值大于0时表示指针e1指向的元素大于指针e2指向的元素,如果数据按升序排序,我们就需要交换两个元素的位置;函数返回值小于0时表示指针e1指向的元素小于指针e2指向的元素;函数返回值小于0时表示两个元素相等。设计好相应的比较函数,我们就可以实现冒泡排序一组任意类型的数据了。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值