C-冒泡排序、qsort、回调函数

目录

1,冒泡排序的原理

2,qsort函数

3,自定义一个类似qsort的排序函数

4,回调函数 


1,冒泡排序的原理

一个数组int arr[] = { 9,8,7,6,5,4,3,2,1,0 },对这个数组按从小到大重新排列。

冒泡排序可以对上述问题进行处理,冒泡排序的原理:将一个数组中的相邻的两个元素做对比,如果arr[i]>arr[i+1],则交换这两个数,两两对比将较大的值往数组的高位移动,直到最后一次数组中只剩下两个数做对比;

以数组{ 9,8,7,6,5,4,3,2,1,0 }为例,

第1趟排序,对数组中的10个数进行9次两两对比,排序后的结果为{ 8,7,6,5,4,3,2,1,0,9 },最大值9放到了最高位。

第2趟排序,对{ 8,7,6,5,4,3,2,1,0,9}进行处理,需要对数组中9个数进行8次两两对比,排序后的结果{ 7,6,5,4,3,2,1,0,8,9},最大值8被放到了次高位。注意:此时两两对比的次数,8和9是不用做对比的,因为第一趟排序已经把9放到了最高位。

第3趟排序,对{ 7,6,5,4,3,2,1,0,8,9}进行处理,......

.......

第9趟排序,对{1,0,2,3,4,5,6,7,8,9}进行处理,对2个数进行1次两两对比,处理后结果为{0,1,2,3,4,5,6,7,8,9}。

排序完成。

#include <iostream>
using namespace std;
#include <string>

void sort(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		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;
			}
		}
	}
}

void main()
{
	int arr[] = { 10,9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(int);

	sort(arr,sz);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ",arr[i]);
	}

	system("pause");
	return;
}

以上代码需注意的:

1,在调用排序函数sort时, 将数组名作为参数传递,函数形参为arr[],此种情况在sort函数调用时也会改变原数组,与函数参数通过指针接收效果一样;

2,排序函数sort只能针对int类型的数组才能起作用;

2,qsort函数

对于多种类型的数据int、float或结构体数组,要进行排序,使用qsort函数,quick sort的缩写。

void qsort (void* base, size_t num, size_t size,
            int (*compar)(const void*,const void*));

以上代码为qsort函数的声明,有四个参数,分别为指向数组的指针、数组元素个数、数组元素类型所占字节、函数指针(指向特定类型对比的函数,函数参数是const void*,返回值类型是int)。

对于不同类型的数组,通过第四个参数(函数指针)指向不同的对比函数,实现对不同类型数组的排序

#include <iostream>
using namespace std;
#include <string>

//对整型数组排序
int cmp_int(const void* e1, const void* e2)
{
	return *((int*)e1) - *((int*)e2);
}

int cmp_float(const void* e1, const void* e2)
{
	return (int)(*((float*)e1) - *((float*)e2));
}
void main()
{
	int arr[] = { 10,9,8,7,6,5,4,3,2,1 };
	float f[] = { 10.0,9.0,8.0,7.0,6.0,5.0,4.0,3.0,2.0,1.0 };

	int sz_arr = sizeof(arr) / sizeof(arr[0]);
	int sz_f = sizeof(f) / sizeof(f[0]);

	qsort(arr, sz_arr, sizeof(arr[0]), cmp_int);

	for (int i = 0; i < sz_arr; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	qsort(f, sz_f, sizeof(f[0]), cmp_float);

	for (int i = 0; i < sz_f; i++)
	{
		printf("%f ", f[i]);
	}

	system("pause");
	return;
}

 上述代码注意事项:

void* 可以指向任何类型的数据,但不可直接对此类型的指针解引用或加减操作,对此类型指针要先强制类型转换后才能使用;

qsort也可以对结构体类型数组进行排序:

#include <iostream>
using namespace std;
#include <string>
struct student 
{
	char name[10];
	int age;
};

int cmp_struct_by_age(const void* e1, const void* e2)
{
	int a = ((student*)e1)->age - ((student*)e2)->age;;
	return a;
}

int cmp_struct_by_name(const void* e1, const void* e2)
{
	int a = strcmp(((student*)e1)->name , ((student*)e2)->name);
	return a;
}
void main()
{
	student stu[3] = { {"zhangsan",20},{"wangwu",30},{"lisi",10} };
	int sz = sizeof(stu) / sizeof(stu[0]);
	//qsort(stu, sz, sizeof(stu[0]), cmp_struct_by_age);
	qsort(stu, sz, sizeof(stu[0]), cmp_struct_by_name);
	system("pause");
}

 对结构体类型数组排序时,既可以根据char类型结构体成员进行排序,也可根据int类型结构体成员进行排序;

当对char类型数组做大小比较时,使用strcmp函数,strcmp函数的返回值如下图:

3,自定义一个类似qsort的排序函数

qsort为库函数,也可以写一个类似qsort的自定义函数:

#include <iostream>
using namespace std;
#include <string>

int cmp_int(const void* e1, const void* e2)
{
	int a = *((int*)e1) - *((int*)e2);
	return a;
}

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

void bubble_sort(void* base,int num,int width,int(*cmp)(const void*,const void*))
{
	int i = 0;
	for (i = 0; i < num-1; i++)
	{
		int j = 0;
		for (j = 0; j < num - 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);
			}
		}
	}
}
void main()
{
	int arr[] = {8,6,7,5,4};
	int num = sizeof(arr) / sizeof(arr[0]);

	bubble_sort(arr, num, sizeof(int), cmp_int);
	for (int i = 0; i < num; i++)
	{
		printf("%d ",arr[i]);
	}
	system("pause");
}

4,回调函数 

自定义的函数bubble_sort与qsort的形参和返回值一样,区别是bubble_sort 中需要根据第四个参数int(*cmp)(const void*,const void*)的返回值,对数组进行排序,也就是要把交换逻辑写出来,对应的交换逻辑函数是void swap(void* e1, void* e2,int width),在swap函数中,根据数据类型的字节数,使用char*类型指针依次交换每个每个字节的存储数据,实现对两个数据的交换。

在自定义的bubble_sort函数中,使用了回调函数的概念,int(*cmp)(const void*,const void*)指向的函数即为回调函数,当指向cmp_int函数时,对int类型数组进行排序,当需要对float类型数组或结构体类型数组排序时,就需要定义对应类型的回调函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值