首页 > 其他分享 >qsort的模拟实现与思路

qsort的模拟实现与思路

时间:2023-03-07 17:32:28浏览次数:29  
标签:自定义 int void qsort 思路 e1 模拟 e2

这是一篇介绍qsort函数模拟实现的博客,包含每一步实现的思路,对MSDN中qsort的使用进行了详细介绍。在实现的过程中,也对涉及到的知识点进行了一些简单介绍。希望可以给同为计算机小白的伙伴们一些帮助,若有错误,还望大佬们不吝赐教。

一、MSDN中对qsort的注解

image.png

1、 功能

执行快速排序; 运用自定义的比较函数,qsort可以对任何类型的数据进行排序;

2、参数

  • void* base image.png目标数组的起点,此参数说明排序从哪开始;  
  • size_t num image.png数组中元素的个数;  
  • size_t width image.png数组中元素所占字节的大小;  
  • int (__cdecl *compare )(const void *elem1, const void *elem2 ) image.pngcompare是一个函数指针,指向一个自定义的比较函数,返回值为int,e1,e2分别为所比较位置的起始位置;

3、标注

image.png qsort是对一个数组执行快速排序的算法,这个数组包含num个元素,每个元素所占字节width个;参数base是指向所需排序数组起点的指针;qsort会将数组中的元素进行排序后覆写;参数compare是用户自定义的函数,通过返回值确定两个元素的大小;qsort会在排序中调用1次或多次此函数,每次调用对两个元素进行排序;image.png默认排序为升序,此时,自定义函数的返回值须满足:e1 < e2,返回值 < 0; e1 = e2,返回值 = 0;e1 > e2,返回值 > 0。若要降序,只需要交换自定义函数中e1,e2的位置即可。  

二、基本功能的实现

1、自定义排序功能

不同于qsort采用快速排序,我们采用冒泡排序作为核心实现排序;

//自定义qsort函数
my_qsort(void* base, int num, int width, int (*cmp)(const void* e1, const void* e2))
{
	//n - 1趟比较
	for (int i = 0; i < num - 1; i++)
	{
		//比较
		for (int j = 1; j < num; j++)
		{
			//交换,cmp返回值大于0则交换位置
			if (cmp(((char*)base + (j - 1) * width), ((char*)base + j * width)) > 0)
			{
				swap(((char*)base + (j - 1) * width), ((char*)base + j * width), width);
			}
		}
	}
}

2、交换元素数据

在自定义函数中,将指针强制类型转换为char*,以交换每一个字节的方式,达到两个字节交换的目的;

//交换
void swap(char* a, char* b, int w)
{
	char tmp = 0;
	for (int i = 0; i < w; i++)
	{
		tmp = *a;
		*a = *b;
		*b = tmp;
		a++;
		b++;
	}
}

3、自定义比较函数

此处我们以整型举例:

  • e1,e2为void*的指针,也就是说从此处访问并不清楚往后访问多少个字节,指针的步长并不确定,我们需要确定步长,也就是说,需要对e1,e2进行强制类型转换;
  • 返回值为int,e1、e2强制类型转换后相减即可得,故代码得以简化;
//整型比较函数
int cmp_int(const void* e1, const void* e2)
{
	return *((int*)e1) - *((int*)e2);
}

以上,对qsort函数的基本功能得以完全实现。  

三、优化及收获

1、排序算法

函数的核心算法,可由冒泡排序改为快速排序,从而降低时间复杂度,从冒泡的O($n^2$)变为快排的O(nlogn)。

2、自定义的打印算法

通过qsort的模拟实现,我们发现: 在函数中,采用void*的指针,通过添加元素个数和元素宽度,一个函数的逻辑可以实现任意类型数据的访问,大大简化代码。

void print(void* a, int sz, int width)
{
	for (int i = 0; i < sz; i++)
	{
		switch (width)
		{
		case 1:
			printf("%c ", *((char*)a + i));
			break;
		case 4:
			printf("%d ", *((int*)a + i));
			break;
		case 8:
			printf("%f ", *((float*)a + i));
			break;
		default:
			break;
		}
	}

标签:自定义,int,void,qsort,思路,e1,模拟,e2
From: https://blog.51cto.com/u_15423682/6106360

相关文章