目录
1.什么是qsort
qsort是C语言的一个函数,它所在的库函数为stdlib
它是将一组相同数据类型的数组元素进行进行排序。
2.cmp的介绍
如果compar返回值小于0(< 0),那么p1所指向元素会被排在p2所指向元素的前面;
如果compar返回值等于0(= 0),那么p1所指向元素与p2所指向元素的顺序不确定;
如果compar返回值大于0(> 0),那么p1所指向元素会被排在p2所指向元素的后面.
同时cmp需要我们自己进行定义,根据所需的类型,转化成相应的数据类型。
如:我们需要比较int 类型变量,我们把p1,p2转化成int类型指针;
int cmp(void *p1, void *p2)
{ return (*(int*)p1 - *(int*)p2); }
我们需要比较char类型变量,我们把p1,p2转化成char类型指针;
int cmp(void *p1, void *p2)
{ return (*(double*)p1 - *(double*)p2); }
我们根据cmp返回值的正负判断,它们是否需要交换。
p1>p2,交换数值;
p1=p2,顺序不确定;
p1<p2,不交换。
我们写的代码当p1>p2时交换,说明是升序。
我们要排降序时,只需p2-p1即可。
接下来我们来使用qsort
3.qsort的使用
练习使用qsort/源.c · 风夏/C语言进阶 - 码云 - 开源中国 (gitee.com)
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
typedef struct stu
{
char name[10] ;
int age;
};
//整形比较
int cmpint(const void* e1, const void* e2)
{
return *(int*)e1 - *(int*)e2;
}
//浮点数比较
int cmpdouble(const void* e1, const void* e2)
{
return (int)(*(double*)e1 - *(double*)e2);
}
//结构体比较
int cmpstuname(const void* e1, const void* e2)
{
return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}
//整形的排序
void test1()
{
int arr[5] = { 1,4,5,6,2 };
int cz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, cz, sizeof(arr[0]), cmpint);
for (int i = 0; i < cz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
//浮点数的比较
void test2()
{
double arr[5] = { 1.0,3.0,2.0,9.0,5.0 };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmpdouble);
for (int i = 0; i < sz; i++)
{
printf("%lf ", arr[i]);
}
printf("\n");
}
//结构体的排序
void test3()
{
struct stu s[3] = { {"zhangsan",15},{"lisi",14},{"wangwu",16} };
int sz = sizeof(s) / sizeof(s[0]);
qsort(s, sz, sizeof(s[0]), cmpstuname);
for (int i = 0; i < sz; i++)
{
printf("%s ", s[i].name);
printf("%d ", s[i].age);
printf("\n");
}
}
int main()
{
//test1();
//test2();
test3();
return 0;
}
*注:这里我们排序了int, double和结构体数据类型,分别为test1,test2,test3
4.利用冒泡排序的方式模拟qsort的实现
4.1思路
我们靠考虑qsort的模拟实现时,我们要考虑的是如何交换不同类型的数据,
我们知道每种数据类型都是以字节为单位,我们交换每个字节的内容即可,交换的范围为每种数据类型所占字节的大小。
4.2代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int cmpint(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+i);
*(e1+i )= *(e2+i);
*(e2+i) = tmp;
}
}
//冒泡排序的原理进行比较
void myqsort(void* dest, int sz, int width, int cmp(const void*,const void*))
{
int i = 0;
int j = 0;
for (i = 0; i < sz-1; i++)
{
for (j = 0; j < sz - 1 - i; j++)
{
//大于1交换
if (cmp(((char*)dest + j * width), ((char*)dest + (j + 1) * width))>0)
//交换的过程
swap(((char*)dest + j * width), ((char*)dest + (j + 1) * width),width);
}
}
}
int main()
{
int arr[5] = { 1,8,3,5,4 };
int sz = sizeof(arr) / sizeof(arr[0]);
//qsort的模拟实现
myqsort(arr, sz, sizeof(arr[0]), cmpint);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
*注:地址的加减要转化为char类型才可以。
5.总结
纸上得来终觉浅,绝知此事要躬行。
如果有任何疑问请评论留言,我将积极解决。
如果对大家有所帮助,请点点赞吧,你的支持是我创作的动力!