模仿qsort实现一个通用的冒泡排序

发布于:2024-06-16 ⋅ 阅读:(22) ⋅ 点赞:(0)

目录

前言

模仿

排序整型数组

排序结构体数组

排序字符数组


前言

qsort在前面我们讲到底层逻辑是快速排序的方式,是不是可以发现有了qsort来进行排序的话,就更加的方便快捷,我们在使用的时候

一方面,代码量会大大的减少

另一方面,可以排序任意类型的数据

是不是发现了这函数的魅力呢?

那么今天我们也来当一个小小开发员来模仿qsort的功能实现一个通用的冒泡排序

我们先来简单的回顾一下冒泡排序:

#include<stdio.h>
void print_arr(int* arr, int sz)
{
	for (int i = 0; i < sz; i++)
		printf("%d ", *(arr + i));
}
void bubble_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 temp = *(arr + j);
				*(arr + j) = *(arr + j + 1);
				*(arr + j + 1) = temp;
			}
		}
	}
}
int main()
{
	int arr[10] = { 2,4,1,6,9,5,3,8,0,7 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	//数组元素个数sz
	printf("排序前:\n");
	print_arr(arr, sz);
	bubble_sort(arr, sz);
	printf("\n排序前:\n");
	print_arr(arr, sz);
	return 0;
}

模仿

目前我们看来,冒泡排序似乎只可以排序整型,那么我们可不可以把它模拟像qsort那样可以排序任意类型的数据呢?

我们一起来试试,既然是模仿qsort那么和qsort应该是一样的函数参数

void imitate_bubble_sort(void* base, int count,int wideth,int (*cmp)(void*,void*))
//  base   ——排序数组的首元素地址
//  count  ——排序数组的元素个数
//  wideth ——排序数组一个元素的字节长度
//  cmp    ——函数指针(具体比较的函数的地址)

不同类型的数据在imitate_bubble_sort函数内部只是比较大小的代码不一样,所以就需要自己写比较的函数。

在比较的时候,因为不同类型的字节数不一样,我们可以根据传过去的width也就是排序数组一个元素的字节长度来访问不同大小的空间进而进行比较,如果满足条件再一个字节一个字节的进行交换,因为正好char类型是一个字节的,我们就可以把void*强制类型转换为char*

排序整型数组

具体代码如下:

#include<stdio.h>
void print_arr(int* arr, int sz)
{
	for (int i = 0; i < sz; i++)
		printf("%d ", *(arr + i));
}
int cmp_int(void* p1, void* p2)
{
	return *((int*)p1) - *((int*)p2);
	//根据具体的数据类型来写
}
void swap(char* p1, char* p2,int width)
{
	for (int i = 0; i < width; i++)
	{
		char temp = *(p1 + i);
		*(p1 + i) = *(p2 + i);
		*(p2 + i) = temp;
	}
	//一个字节一个字节进行交换
}
void imitate_bubble_sort(void* base, int count,int width,int (*cmp)(void*,void*))
//  base   ——排序数组的首元素地址
//  count  ——排序数组的元素个数
//  wideth ——排序数组一个元素的字节长度
//  cmp    ——函数指针(具体比较的函数的地址)
{
	int i = 0;
	for (i = 0; i < count - 1; i++)//趟数
	{
		int j = 0;
		for (j = 0; j < count - 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);
		}
	}
}
int main()
{
	int arr[10] = { 2,4,1,6,9,5,3,8,0,7 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	//数组元素个数sz
	printf("排序前:\n");
	print_arr(arr, sz);
	imitate_bubble_sort(arr, sz, sizeof(int), cmp_int);
	printf("\n排序后:\n");
	print_arr(arr, sz);
	return 0;
}

这里我们可以看到,它成功排序了整型,那么其它类型的数据可不可以呢?

排序结构体数组

我们来试试结构体类型的:

#include<stdio.h>
#include<string.h>//strcmp头文件
struct Student
{
	char name[20];
	int age;
};
void print_arr(struct Student* arr, int sz)
{
	for (int i = 0; i < sz; i++)
		printf("%s %d\n", (arr + i)->name, (arr + i)->age);
}
int cmp_student_by_name(void* p1, void* p2)
{
	return strcmp(((struct Student*)p1)->name, ((struct Student*)p2)->name);
}
void swap(char* p1, char* p2, int width)
{
	for (int i = 0; i < width; i++)
	{
		char temp = *(p1 + i);
		*(p1 + i) = *(p2 + i);
		*(p2 + i) = temp;
	}
}
void imitate_bubble_sort(void* base, int count, int width, int(*cmp)(void*, void*))
{
	int i = 0;
	for (i = 0; i < count - 1; i++)
	{
		int j = 0;
		for (j = 0; j < count - 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);
		}
	}
}
int main()
{
	struct Student stu_arr[3] = { {"lihua",24},{"wangdan",56},{"anna",18} };
	int sz = sizeof(stu_arr) / sizeof(stu_arr[0]);
	printf("排序前:\n");
	print_arr(stu_arr, sz);
	imitate_bubble_sort(stu_arr, sz, sizeof(stu_arr[0]), cmp_student_by_name);
	printf("\n排序后:\n");
	print_arr(stu_arr, sz);
	return 0;
}

排序字符数组

#include<stdio.h>
#include<string.h>
void print_arr(char* arr, int sz)
{
	for (int i = 0; i < sz; i++)
		printf("%-3c", arr[i]);
}
int cmp_char(void* p1, void* p2)
{
	return strcmp((char*)p1, (char*)p2);
}
void swap(char* p1, char* p2, int width)
{
	for (int i = 0; i < width; i++)
	{
		char temp = *(p1 + i);
		*(p1 + i) = *(p2 + i);
		*(p2 + i) = temp;
	}
}
void imitate_bubble_sort(void* base, int count, int width, int(*cmp)(void*, void*))
{
	int i = 0;
	for (i = 0; i < count - 1; i++)
	{
		int j = 0;
		for (j = 0; j < count - 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);
		}
	}
}
int main()
{
	char c[] = "dnjffskajkb";
	//c——字符数组
	int sz = sizeof(c) / sizeof(c[0]);
	printf("排序前:\n");
	print_arr(c, sz);
	imitate_bubble_sort(c, sz, sizeof(c[0]), cmp_char);
	printf("\n排序后:\n");
	print_arr(c, sz);
	return 0;
}

可以看见无论是结构体数组,还是字符数组,我们的代码得到了我们想要的结果!