利用冒泡排序模拟(创造)qsort函数

目录

前言:

1 :将冒泡排序与qsort联系:

1.1 :参数接收变化:

1.1.1 :" int* arr "

1.1.2 :" int sz " 与 比较函数

1.1.3 :变为

1.2 :冒泡函数内部变化

1.2.1 :第一处

1.2.2 :第二处

1.3 :对于Swap(交换)函数的构建

2 :最终代码


前言:

        我们在模拟qsort函数的时候,我们要联想到当初作者实在怎么样的一个环境下,所书写的代码。作者在书写的时候,是不知道用户会用什么样的来进行比较,并排序,所以我们所要注意,我们要巧妙的运用 void* 与 char* 的特性来,进行完成我们所模拟的代码。


1 :将冒泡排序与qsort联系:

首先以一个冒泡排序完成排序代码。

#include <stdio.h>

void bubble(int* arr, int sz)
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int 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 print(int* arr, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

int main()
{
	int arr[10] = { 10,9,8,7,6,5,4,3,2,1 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble(arr, sz);
	print(arr, sz);
	printf("\n");
	return 0;
}

1.1 :参数接收变化:

        我们可以发现,冒泡排序所必须的就是传入一个字符串的起始地址,便于向后寻找数据,但是由于函数不知数组的范围,位置需传入一个sz,这样的情况下才能保证遍历每个元素。但这是基于我们知道传的什么类型的数据,并将其书写为 " void bubble(int* arr, int sz) " 。我们要知道,qsort函数的作者,能不能想到我们所使用qsort会排序怎样的一个具体的数据类型的数据?那当然是不知道的。于是我们就要针对其经行修改。

1.1.1 :" int* arr "

        我们不知道他的类型,但是首元素又要经进行传参,于是将其变为:

void* arr, int width

        以 " void* " 进行直接的接受,并让其不具备任何的类型,这样我们就得到了首元素的地址,并且可以接收任意的类型的数组。但是,要知道这样的指针类型,根本无法告诉函数一个元素的大小的,这会导致使得后方的冒泡排序的调换部分出现问题,之前的冒泡排序因为,以清晰的指针类型进行了接受,可以进行完美的调换。但是这里不行,于是我们需要将一个元素的宽度传入。

1.1.2 :" int sz " 与 比较函数

        对于 " int sz " 因为对于任意类型的函数都可以兼容的传入,无需考虑其的问题,于是不变即好。

        对于比较函数,再qsort中就是我们必须要写的,这里就以自行创造bubble_qsort冒泡排序函数的角度从零到一:

  1. 比较是两个元素之间需进行的,所以需要 e1,e2 。
  2. 对于两个元素我们只是进行比较,并不进行改变,于是二者皆以 const 定义。
  3. 在冒泡排序中有一个if语句,用于判断二者是否需要进行调换。于是我们将:前者大于后者返回>0;前者等于后者返回=0;前者小于后者返回<0。这样便有了比较函数。

参数接收变化如下:

int sz ,int cmp_int(const void* e1, const void* e2)

比较函数如下(以int类型的数据为例):

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

1.1.3 :变为

void bubble_qsort(void* arr, int sz , int width,int cmp_int(const void* e1, const void* e2))
{
    ;//此处省略实现代码
}

1.2 :冒泡函数内部变化

void bubble(int* arr, int sz)
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int 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;
			 //-----------------------第二处
            }
		}
	}
}

1.2.1 :第一处

        此处我们要将所需要比较的内容数据传参给 cmp_int  函数,但是,我们要知道,在 bubble_qsort 函数接受中 , 我们将arr首元素的地址以 void*的指针进行的接受。对于cmp_int  函数所需要多次的使用,比较不同组的数据,但是由于,其没有实际的类型的,无法进行直接使用(指针的解引用与加减等)。于是,我们需要对其去进行强制类型转换。但是,对于各种的类型而言,其的字节大小皆是>=1的,因此我们最佳的选择就是将其强制类型转换为 char* 的指针。这样我们将元素的地址进行输出,用户再从cmp_int  函数中对其强制类型转换为其对应的类型进行比较即可。

        对于,例如:啊arr[0]与arr[1], arr[1]与arr[2]。这样的多组比较,在原冒泡排序中为 " arr [ j ] > arr [ j  + 1 ] " 。然而对于以转换为 char* 指针来说,这种方法肯定是不行的了,因为原来是具备其真实的类型的。所以之前说传入的width就起作用了,width 可以表示为,第一个元素的地址到第二个元素的地址,其距离的字节距离。

void bubble(int* arr, int sz)
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int j = 0; j < sz - 1 - i; j++)
		{
			 //----------------------------------------------------------------
            if (cmp_int((char*)arr + j * width, (char*)arr + (j + 1) * width))    
			{//----------------------------------------------------------------第一处				  
                int tmp = arr[ j ];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
            }
		}
	}
}

1.2.2 :第二处

        在原本的冒泡排序中,可以进行直接的调换,是因为函数清楚的知道其的类型。在bubble_qsort 函数中同样的问题,于是也选择为转换char*类型,并以同样的方式转化:

void bubble(int* arr, int sz)
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int j = 0; j < sz - 1 - i; j++)
		{
            if (cmp_int((char*)arr + j * width, (char*)arr + (j + 1) * width))    
			{			
             //---------------------------------------------------------------------  
				Swap((char*)arr + j * width, (char*)arr + (j + 1) * width, width);
			 //---------------------------------------------------------------------第二处
            }
		}
	}
}

1.3 :对于Swap(交换)函数的构建

        此处,我们以*e1 = 10000000,*e2 = 9000000为例。。那么为了类型的多样化,我们可以将地址以char*类型的指针接受。然后更具一个字节为一个单位进行交换:80与40换,96与54换,98与89换,00与00换。这样就相当于int类型的数据进行交换。

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

2 :最终代码

#include <stdio.h>
#include <stdlib.h>

//比较大小
int cmp_int(const void* e1, const void* e2)
{
	return (int*)e1 - (int*)e2;
}

//数据交换
void Swap(char* e1, char* e2, int width)
{
	for (int i = 0; i < width; i++)
	{
		char tmp = *e1;
		*e1 = *e2;
		*e2 = tmp;
		e1++;
		e2++;
	}
}

//冒泡排序
void bubble_qsort(void* arr, int sz , int width,int cmp_int(const void* e1, const void* e2))
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int j = 0; j < sz - 1 - i; j++)
		{
			if (cmp_int((char*)arr + j * width, (char*)arr + (j + 1) * width))
			{
				Swap((char*)arr + j * width, (char*)arr + (j + 1) * width, width);
			}
		}
	}
}

//数组输出
void print(int* arr, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}

int main()
{
	int arr[10] = { 10,9,8,7,6,5,4,3,2,1 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_qsort(arr, sz, sizeof(arr[0]),cmp_int);
	print(arr, sz);
	printf("\n");
	return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

川入

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值