!!‧✧̣̥̇‧✦‧✧̣̥̇‧✦ ‧✧̣̥̇:Solitary-walk
⸝⋆ ━━━┓
- 个性标签 - :来于“云”的“羽球人”。 Talk is cheap. Show me the code
┗━━━━━━━ ➴ ⷯ本人座右铭 : 欲达高峰,必忍其痛;欲戴王冠,必承其重。
自
信
希望在看完我的此篇博客后可以对你有帮助哟此外,希望各位大佬们在看完后,可以互赞互关一下,看到必回
时隔多日,重出江湖! 今日给大家 share 一个关于如何实现qsort()
目录
首先想要实现此函数的模拟,我们就必须先了解qsort()
函数返回值:
看不懂,木有关系,接下来我逐一解释
void qsort ( void* base, size_t num, size_t size, int (*compar)(const void*,const void*) );
第一个参数void* base:指向要比较首元素的地址,注意因为不知道要比较数据的类型,所以这里是void*
第二个参数:size_t num,所比较数组的元素 个数
第三个参数:size_t size 每个元素 所占字节的大小
第四个参数:int (*compar)(const void*,const void*) 是一个函数指针,这是用户自己设计的一个函数,用来比较元素大小
用此函数实现对数据的快速排序
数组:int arr[ ] = { 2,3,1,6,5,4,7,8,9,10 };
思路:我们用户需要自己写一个函数来实现元素比较大小的
注意此函数的返回类型必须是int
其次我们需要传入2个指针
函数的形参必须是:(const void* p1, const void* p2)
完整版代码:
#include
#include
int cmp(const void* p1, const void* p2)
{
return (*(int*)p1) - (*(int*)p2);//没有必要进行大小比较,直接做差即可
}
void Print(int arr[], int sz)
{
int i = 0;
for(i = 0;i < sz;i++)
{
printf("%d ", arr[i]);
}
}int main()
{
int arr[] = { 2,3,1,6,5,4,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort( arr, sz, sizeof(int), cmp);
//qsort()有4个参数:待排序数组首元素地址,待排序元素个数,每个元素的大小,函数的地址(函数指针)
Print(arr, sz);
return 0;
}
这里我们借助冒泡排序的思想,来模拟实现
所以我们核心逻辑还是双层for循环
那么我们就需要考虑以下问题:
1)如何从指定的数据类型(int)来实现对任意数据类型的比较?
===》这里写成 void*
2)2相邻元素也不能直接进行比较,因为数据具体类型我们是未知的
===》这里我们借助函数指针来实现队任意数据类型比较
注意对于void*类型指针不能直接解引用,也不能直接进行指针运算
这里我们强转成char*类型指针,可以一个字节一个字节进行比较
这里我们需要把下标为j所对应元素地址传过去:又因为每个数据所占字节我们已知:size
所以下标为 j 所对应元素地址:(char*)base + j * size
同上:下标为 j+1 所对应元素地址:(char*)base + (j+1) * size
void Qsort(void* base, int num, int size, int (*cmp)(const void* p1, const void* p2))
{
for (int i = 0; i < num-1; i++)//确定一共进行多少趟
{
//一趟排序 需要交换的对数
for (int j = 0; j < num - 1 - i; j++)
{
//默认是按升序进行排列
if (cmp((char*)base + j * size, (char*)base + (j + 1) * size ) > 0)//这里必须写上>0
{
//进行交换
Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);//在这里必须把要比较元素大小传过去
}
}
}
}
接下来就是如何实现2元素交换?
这里我们是一个字节一个字节来进行交换的
void Swap(char* p1, char* p2, int size)
{
//注意这里是一个字节一个字节进行交换
/*
char* tmp = NULL;
for (int i = 0; i < size; i++)
{
以下只是改变了指针的位置,并没有实现我数据 的交换,注意交换你本质是内容交换,所以需要先解引用
tmp = p1;
p1 = p2;
p2 = tmp;
p1++, p2++;
}*/
//正确代码
char tmp = 0;
for (int i = 0; i < size; i++)
{
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++, p2++;
}
}
qsort()完整版代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include
// 以冒泡排序的思想模拟实现 qsort快速排序 注意这里用户需要根据自己需要写一个比较函数
//需要解决以下 问题:1) 实现对各种数据类型的模拟 2)对于2个元素的交换不仅仅是int类型数据
void Swap(char* p1, char* p2, int size)
{
//注意这里是一个字节一个字节进行交换
/*
char* tmp = NULL;
for (int i = 0; i < size; i++)
{
以下只是改变了指针的位置,并没有实现我数据 的交换,注意交换你本质是内容交换,所以需要先解引用
tmp = p1;
p1 = p2;
p2 = tmp;
p1++, p2++;
}*/
//正确代码
char tmp = 0;
for (int i = 0; i < size; i++)
{
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++, p2++;
}
}
void Qsort(void* base, int num, int size, int (*cmp)(const void* p1, const void* p2))
{
for (int i = 0; i < num-1; i++)//确定一共进行多少趟
{
//一趟排序 需要交换的对数
for (int j = 0; j < num - 1 - i; j++)
{
//默认是按升序进行排列
if (cmp((char*)base + j * size, (char*)base + (j + 1) * size ) > 0)//这里必须写上>0
{
//进行交换
Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);//在这里必须把要比较元素大小传过去
}
}
}
}
int cmp(const void*p1, const void*p2)//用户自己设计的
{
return (*(int*)p1) - (*(int*)p2);
}
void Print(int* p, int sz)
{
for (int i = 0; i < sz; i++)
{
printf("%d ", *p);
p++;
}
}
int main()
{
int arr[] = { 7,4,1,2,5,8,3,6,9,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
Qsort(arr, sz, sizeof(arr[0]), cmp);
Print(arr, sz);
return 0;
}
运行结果:
ok~~以上就是今日我要为各位老铁的分享,要是感觉还不错的话,点个赞,互关一下呗