前言:
小编在上一篇文章说了这一篇将要写qsort函数的模拟实现,那么废话不多说,现在开始进入今天的代码之旅喽!
目录:
1.qsort函数的模拟实现的逻辑和思路
2.qsort函数模拟实现的代码实现
3.代码展示
1.qsort函数的模拟实现的逻辑和思路
读者朋友们是否还记得小编之前说过的一个排序的算法:冒泡排序,今天我们就是用它来模拟实现qsort函数的,如果有读者朋友略微忘记的话,小编先从这里呈现冒泡排序代码的实现来让读者朋友们回忆部分内容:
void my_paopao(int arr[10], int sz)
{
int i = 0;
int flag = 1;
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 tmo = 0;
tmo = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmo;
flag = 0;
}
if (flag == 1)
break;
}
}
}
int main()
{
int arr[10] = { 0 };
int i = 0;
for (i = 0; i < 10; i++)
{
scanf("%d", arr + i);
}
int sz = sizeof(arr) / sizeof(arr[0]);
my_paopao(arr, sz);
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
上面就是冒泡排序代码的实现,如果稍微有点记不清的读者朋友可以看上述代码回忆一下,或者浏览:C语言重要算法之一——冒牌排序详解(干货满满,欢迎各位朋友的观看)-CSDN博客 ,这个是我以前写过的博客,大家可以看这个回顾,回归正题,我们知道,冒泡排序只能排序整型,而qsort函数可以排序任意类型的数组,我们可以以冒泡排序为整体的框架,从而可以模拟qsort函数。
首先,我们先来回顾一下,qsort函数内部的内容,通过上次小编介绍的网站可以清晰的看到:
我们可以先仿照这个来先写一个类似的函数,因为这个是我们自己模拟的,所以可以自己命名,我们对函数描述完以后,就要写函数的主题了,小编前面说过,我们可以保留冒泡排序的框架,所以我们先把代码拿出来来进行思考:
void my_qsortvoid *base,size_t count,size_t width,int (*cop)(const void* p1,const void* p2) ) //这里完全对照qsort函数本身括号内部的内容
{
int i = 0;
int flag = 1;
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 tmo = 0;
tmo = arr[j];
arr[j] = arr[j + 1]; //当然我们不能这么比较,因为我们有可能设计到字符的比较,对于改进我们在下面叙说,毕竟咱不能一口气吃个小编
arr[j + 1] = tmo;
flag = 0;
}
if (flag == 1)
break;
}
}
}
正如我在上面所说,我们可以把循环给保存好,然后对于内容进行修改,不知道读者朋友们是否还记得小编之前说过qsort是怎么判定可以交换的,如果忘记了请看下图 :
当返回值大于0的时候将会让两个数进行交换,小于0或者等于0的时候是不发生交换的,那么这个时候,我们就可以我们写的最后一个函数(括号最后一个)指针来进行比较操作,通过此函数的返回值来比较是否大于0,如果大于0再进行交换操作。
交换操作可以通过我们再写一个交换函数来进行数值的交换,我们在交换的时候,要考虑到我们传参的时候不一定传的就是整型,我们上面式子的交换是只是针对整形的,对于字符型的,小编认为,我们可以通过一个一个字节的来进行交换,这样的话,我们既可以针对字符型,也可以针对整型了,现在我们已经有了这个函数的大致思路了,下面就我们就来进行函数的写正式描写喽!
2.qsort函数模拟实现的代码实现
我们刚开始就要先写一下函数名,通过我们对于qsort函数的了解,下面是代码的实现:
int arr[10] = { 3,4,5,6,7,8,9,10,1,2 };
int sz = sizeof(arr) / sizeof(arr[0]);
my_qsort(arr, sz, sizeof(arr[0]), com_per); //这里放函数名就好
之后,我们就要进行比较环节了,循环方面小编就不写了(待会会把完整的代码发出来,大家不要着急),我们首先要靠比较函数来比较大小,对于这方面的实现,我们其实可以完全仿照我们之前运用比较函数的样子,首先我们要先写一个if语句来判定它与0之间的大小关系,下面是代码呈现:
if (cop((char*)base + j * width, (char*)base + (j+1) * width) > 0)
{
comper((char*)base + j * width, (char*)base + (j + 1) * width, width); //这是交换的(适用于任何的数)
}
对于函数如何进行比较,小编放在了下图,完全可以仿照我们使用它的时候的比较进行书写(我们这里就以char类型的数据举例):
int com_per(const void* p1, const void* p2)
{
return ((*(char*)p1) - (*(char*)p2)); //对于字符串的比较才用strcmp
}
所以说,比较函数我们就原封不动的写就好(此时也是展现了为什么这么比较就可以实现两个数的交换),之后就到了我们这个代码的重头戏,对于我们如何进行两个数的交换,小编在思路部分就说了,我们可以实现一个字节一个字节的交换从而完成所有的交换,所以我们可以直接用char*指针对于我们比较两个数进行接受,然后我们可以写一个循环,通过这个循环来实现每个字节的交换,对于次数的限制,我们就以我们比较数的大小作为最大次数,从而实现字节的交换,我光说可能大家都很疑惑,下面是完整的代码展示:
void comper(char* a1, char* a2,int width)
{
int i = 0;
char a = 0;
for (i = 0; i < width; i++)
{
a = *a1;
*a1 = *a2;
*a2 = a;
a1++;
a2++;
}
}
上面便是对于这个交换函数进行的描写,与小编说的一样,此时我们通过循环便可以实现每个数的交换,可能有些读者很疑惑,认为整型是怎么实现交换的,为此小编通过图文的形式进行解释:
虽然小编画的有点抽象,但是是这么个道理,这里确实实现了两个数的交换,那么我们通过每次循环,来对于数进行交换了,最终会实现此代码的实现,下面来展示一下这个代码最后的运行图:
可以很清楚的看已经完成了升序环节,证明此函数模拟成功了,可能现在还有很多读者朋友不知道如何完整的实现这个功能,不要急,小编这就给大家展示源代码!
3.代码展示
小编这里就拿整型和字符型来进行展示了
整型的主函数:
int arr[10] = { 3,4,5,6,7,8,9,10,1,2 };
int sz = sizeof(arr) / sizeof(arr[0]);
my_paopao(arr, sz, sizeof(arr[0]), com_per); //这里放函数名就好
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
模拟函数(这里通用的,所以下面也不展示了):
void my_paopao(void *base,size_t count,size_t width,int (*cop)(const void* p1,const void* p2)) //这里是模仿的qsort里面的内容来写的
{ //上面也用到了回调函数的思想
int i = 0;
for (i = 0; i < count - 1; i++) //这里采用的模板是按照冒泡排序的思想来写的,外在并没被改变,但是内在却和冒泡排序是截然不同的
{
int j = 0;
for (j = 0; j < count - i - 1; j++)
{
if (cop((char*)base + j * width, (char*)base + (j+1) * width) > 0)
{
comper((char*)base + j * width, (char*)base + (j + 1) * width, width); //这是交换的(适用于任何的数)
}
}
}
}
比较函数:
int com_per(const void* p1, const void* p2)
{
return (*(int*)p1 - *(int*)p2);
}
交换函数(这个是通用的,小编下面就不写了):
void comper(char* a1, char* a2,int width)
{
int i = 0;
char a = 0;
for (i = 0; i < width; i++)
{
a = *a1;
*a1 = *a2;
*a2 = a;
a1++;
a2++;
}
}
字符型主函数:
char arr[10] = { 'a','c','d','b','e','h','q','u','x','z' };
int sz = sizeof(arr) / sizeof(arr[0]);
my_paopao(arr, sz, sizeof(arr[0]), jisuan);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%c ", arr[i]);
}
比较函数:
int jisuan(const void* p1, const void* p2)
{
return ((*(char*)p1) - (*(char*)p2)); //对于字符串的比较才用strcmp
}
总结;
小编先声明一下,小编这里是用冒泡排序的方式来模拟实现这个函数的,但不一定代表着只有冒泡排序才可以模拟实现这个函数,对于这个函数的具体实现可能也就只有制作这个函数的人知道了,读者朋友们学会其中的思想就好了,在这里,小编也是连着更了七天的博客了,在这期间我也发现了我忘记了很多知识,果然还是那句话:温故而知新可以为师矣 !,大家平常一定要多复习自己学过的知识,避免忘记过多,明天可能会停更一天,小编歇一天,如果文章有错误,恳请大家指出,小编虚心求教,我们下一篇博客见喽!