C/C++qsort函数的实现(冒泡排序)

 个人主页:

仍有未知等待探索_数据结构,小项目,C语言疑难-CSDN博客

专题分栏:

C语言疑难_仍有未知等待探索的博客-CSDN博客

目录

一、引言

二、讲解实现

1、给整型数组排序 

 排序实现

总代码 

2、qsort中参数cmp函数怎么实现

1.浮点型

2.结构体类型 


一、引言

1、第一个参数是void*base:指向要排序的数组的第一个对象的指针,转换为 void*。

2、第二个参数是size_t num:数组中按基数指向的元素数。size_t是无符号整数类型。

3、第三个参数是size_t  size:数组中每个元素的大小(以字节为单位)size_t是无符号整数类型。

4、第四个参数是int (*compar)(const void*p1,const void*p2)):指向比较两个元素的函数的指针。

大家是不是很疑惑,咱们写冒泡排序或者选择排序的时候,感觉也没有那么的复杂,为什么C语言库函数中qsort函数的参数那么的麻烦。为什么还要传size_t size呢?大家是不是会有这样的疑问呢?今天我就给大家详细的讲解一下!(库函数中qsort函数是快速排序,我用冒泡排序实现) 

二、讲解实现

1、给整型数组排序 

 首先,我们需要先把自定义函数的参数给设计好,但是因为我们是实现库函数中的qsort函数,所有我们就直接把库函数中的参数写出来就行了。

我们现在要排序的是整型数组,所以也需要一个整型数组。

sz是为了计算出数组的长度。

问:为什么自定义函数的接收数组的参数类型是void*,而不是int*呢?

答:void* 是一种无类型指针,可以指向任意类型的数据,无需强制类型转换。意思就是说,当你把数组arr传给void*base的时候,不用管为什么base的类型不是int*,可以把void*类型理解为一个万能的类型。(注意:void*类型的变量,不能直接进行解引用访问,也不能进行指针运算,想进行上述操作必须进行强制类型转化)

#include<stdio.h>
int cmp(void* x, void* y)
{
	return *(int*)x - *(int*)y;
}
//声明自定义排序函数
void qsort_m(void* base, size_t num, size_t size,int (*compar)(const void* p1, const void* p2));
int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1 };//提供一个整型数组
	int sz = sizeof(arr) / sizeof(arr[0]);//计算数组的长度
	qsort_m(arr, sz, sizeof(arr[0]), cmp);//自定义排序函数的调用
	int i = 0;
	for (i = 0; i < sz; i++)//输出
		printf("%d ", arr[i]);
	return 0;
}

 排序实现

void qsort_m(void* base, size_t num, size_t size, int (*compar)(const void* p1, const void* p2))
{
	int i = 0, j = 0;
	for (int i = 0; i < num - 1; i++)
	{
		for (int j = 0; j < num - 1 - i; j++)
		{
			if (compar(((char*)base + j * size), (char*)base + (j + 1) * size) > 0)
			{
				//交换
				swap((char*)base + j * size, (char*)base + (j + 1) * size,size);
			}
		}
	}
}

compar(((char*)base + j * size), (char*)base + (j + 1) * size),这块要把base强转为char*类型,目的是这个char*能表示更多的数据类型,char*解引用仅能得到一个字节的数据,而int*等其他的类型解引用之后,能得到更多的字节的数据均比char*的大,所以用char*类型可以得到所有传进来的数据,所以,到这里就明白了,为什么要传入数据类型的大小,j*size是为了让数组访问下一个空间的数据。

 最后就剩一个比较简单的交换函数。

void swap(char* buf1, char* buf2, size_t size)
{
	int i = 0;
	for (int i = 0; i < size; i++)
	{
		int tmp;
		tmp = *(buf1 + i);
		*(buf1 + i) = *(buf2 + i);
		*(buf2 + i) = tmp;
	}
}

总代码 

#include<stdio.h>
int cmp(void* x, void* y)
{
	return *(int*)x - *(int*)y;
}
void swap(char* buf1, char* buf2, size_t size);
void qsort_m(void* base, size_t num, size_t size, int (*compar)(const void* p1, const void* p2));
int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1 };//提供一个整型数组
	int sz = sizeof(arr) / sizeof(arr[0]);//计算数组的长度
	qsort_m(arr, sz, sizeof(arr[0]), cmp);//自定义排序函数的调用
	int i = 0;
	for (i = 0; i < sz; i++)//输出
		printf("%d ", arr[i]);
	return 0;
}
void qsort_m(void* base, size_t num, size_t size, int (*compar)(const void* p1, const void* p2))
{
	int i = 0, j = 0;
	for (int i = 0; i < num - 1; i++)
	{
		for (int j = 0; j < num - 1 - i; j++)
		{
			if (compar(((char*)base + j * size), (char*)base + (j + 1) * size) > 0)
			{
				//交换
				swap((char*)base + j * size, (char*)base + (j + 1) * size,size);
			}
		}
	}
}
void swap(char* buf1, char* buf2, size_t size)
{
	int i = 0;
	for (int i = 0; i < size; i++)
	{
		int tmp;
		tmp = *(buf1 + i);
		*(buf1 + i) = *(buf2 + i);
		*(buf2 + i) = tmp;
	}
}

2、qsort中参数cmp函数怎么实现

        cmp是一个函数指针,这个函数指针指向的是一个函数,这个函数的返回值是int类型的。当返回值<0 ,p1 指向的元素先于 p2 指向的元素 ;返回值=0 ,p1 指向的元素等效于 p2 指向的元素;返回值 >0 ,p1 指向的元素在 p2 指向的元素之后。

如果想详细的知道的话,请点链接,看我上一篇。 

C语言qsort函数的使用_仍有未知等待探索的博客-CSDN博客

1.浮点型

int cmp(const void* p1, const void* p2)
{
	return *(float*)p1 - *(float*)p2;
}

2.结构体类型 

typedef struct Stu
{
	char name[20];
	int score;
}Stu;
int cmp(const void* p1, const void* p2)
{
	return ((Stu*)p1)->score - ((Stu*)p2)->score;
}
int main()
{
	Stu s[3] = { { "张三",50 }, { "王五",70 }, { "李四",60 } };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp);
	for (int i = 0; i < sz; i++)
		printf("%s %d\n", s[i].name,s[i].score);
	return 0;
}

最后、谢谢大家的支持 !

猜你喜欢

转载自blog.csdn.net/qq_73435980/article/details/133203433
今日推荐