能排序任意数据类型数组的冒泡排序的实现

1.从qsort函数中得到启示

C语言中有一个库函数qsort,可以实现对任意类型数组进行排序,其函数声明如下

其中base是数组首元素地址,num是无符号整型,意为数组元素个数,size是数组元素中每个元素的大小,单位为字节,而最后一个是一个函数指针,指向的函数会告诉计算机比较两元素的方法,比如比较两个结构体的大小,不能直接想1<2那样简单的直接比较,可以根据结构体中的元素进行比较,比如

typedef struct stu
{
	int age;
	char name[20];
}stu;

这个结构体,可以比较age得出两个结构体之间的大小关系,也可以比较name字符串得出二者大小关系。qsort中的函数指针就是指向这样的一个函数,这个函数返回值为int,若返回值大于0,则前大于后。

2.改造冒泡排序

void bubble(int arr[], int sz)
{
	int i, j;
	for (i = 0; i < sz - 1; i++)
	{
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}

这个冒泡排序中int arr[]是需要改变的,同时if语句中的两元素比较也需要改变,还有两元素的交换也需要改变,因为不清楚是什么类型的数据,就不能确定临时变量tmp的类型。同时该函数参数也与qsort一致。

3.代码实现

函数参数与qsort一致,这里以比较上面stu结构体的name为例。

void bubble_sort(void* base, size_t num, size_t len, int(*pf)(const void* p1, const void* p2))

base是首元素地址,num是数组元素个数,len是单元素大小,pf是函数指针。

同时实现比较函数。将两个元素的地址传过去。

int name_cmp(const void* p1, const void* p2)
{
	return strcmp(((stu*)p1)->name, ((stu*)p2)->name);
}

之后是交换函数,还是传两个元素的地址。

void swap(void* p1, void* p2, size_t len)
{
	size_t i;
	for (i = 0; i < len; i++)
	{
		char tmp = *((char*)p1 + i);
		*((char*)p1 + i) = *((char*)p2 + i);
		*((char*)p2 + i) = tmp;
	}
}

要交换两个元素,只需要将每个元素单个字节的元素交换就行了,例如某元素四个字节

只要像这样交换每个字节的数字就可以了,为此需要将p1,p2类型强制转化为char*类型,因为char* 指针可访问的大小为一个字节。

void swap(void* p1, void* p2, size_t len)
{
	size_t i;
	for (i = 0; i < len; i++)
	{
		char tmp = *((char*)p1 + i);
		*((char*)p1 + i) = *((char*)p2 + i);
		*((char*)p2 + i) = tmp;
	}
}

最后是bubble_sort实现

void bubble_sort(void* base, size_t num, size_t len, int(*pf)(const void* p1, const void* p2))
{
	int i, j;
	for (i = 0; i < num - 1; i++)
	{
		for (j = 0; j < num - 1 - i; j++)
		{
			if (pf((char*)base+j*len,(char*)base+(j+1)*len) > 0)
			{
				swap((char*)base + j * len, (char*)base + (j + 1) * len,len);
			}
		}
	}
}//num是需要排序的元素个数,len是一个元素的字节长度,base是首元素的地址,pf是一个函数指针,指向一个声明元素比较方法的函数

测试一下

int main()
{
	stu s[4] = { {13,"roboko"},{11,"naruto"},{15,"sasuke"},{18,"sakura"} };
	bubble_sort(s, 4, sizeof(stu), name_cmp);
		for (int i = 0; i < 4; i++)
		{
			printf("%s\n", s[i].name);
		}
	return 0;
}

 

打印结果确实是从小到大排序的。

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值