一、1.函数了解:在c语言中qsort函数是一个排序函数,它不光可以排序整数,字符,也可以根据结构体的组成成分来排序结构体,它在c语言库中是通过快速排序的方式来实现,其头文件为stdlib.h。
2.qsort函数:从上面我们知道qsort是一个排序的函数,所以并不需要返回值,qsort函数有四个参数,按顺序依次为 待排序元素的首地址(指针),排序数组元素的个数,一个元素所占的字节,函数指针。
3,qsort如何实现排序的:qsort函数的最后一个参数是一个函数指针,它所指向的函数可以比较两个数的大小,根据返回值来决定是否交换两个数,如果返回值为正数则交换。我们知道该函数可以比较各种类型的数据,所以我们需要将比较的两个数的类型以void形式传入比较函数,同时为了防止自己改变指针所指向的内容,我们给其限定const。
四、函数实现:
我们这里使用的是冒泡排序的方式实现排序,所以想要完成以下代码请先学习冒泡排序;
1、我这里先使用整形数组实现,便于理解,在文章后面会给出字符类型的实现形式:
void test()
{
int arr[10]={3,4,5,2,1,6,7,8,9,0};//输入乱序的元素
int sz=sizeof(arr)/sizeof(arr[0]);//求出数组元素的个数
my_qsort(arr,sz,sizeof(arr[0]),compar);//按照传参顺序依次输入
int *p=arr;
print(p,sz);
}
int main()
{
test();
return 0;
}
下面就是比较两元素大小的函数
int compar(const void*p1,const void*p2)
{
return *(int*)p1-*(int*)p2;//通过返回值来判断是否交换元素
//你要排序什么元素就将p1,p2强制转化为什么类型
//例如return strcmp(((struct stu*)p1)->name,((struct stu*)p2)->name);
//strcmp为字符串比较函数,其返回值也为0或1
}
当上面这个函数返回一个int的数据时我们需要根据正负来确定是否交换元素,我们知道该函数可以交换各种类型的数据,那么我们就需要字节来作为最小单位,因为我们知道int(4字节),char(1个字节),如果我们定义最小交换字节为4的话是实现不了字符类型数据的交换:
void my_qsort(void*p,size_t sz,size_t width,int (*ptr)(const void*,const void*))
{//size_t是无符号整型,因为传的参数是数组的大小,以及单个元素所占的字节,其值为整数
//最后一个函数就是传入比较函数的地址以便下面使用
int i=0;
for(i=0;i<sz-1;i++)
{
for(int j=0;j<sz-i-1;j++)
{
if(compar((char*)p+j*width,(char*)p+(j+1)*width)>0)
{
sweap((char*)p+j*width,(char*)p+(j+1)*width,width);
//通过冒泡排序的形式来比较两个数据的大小,最后通过sweap函数来
//交换比较的函数
}
}
}
}
下面就是完成交换的函数,上面我们说过比较的数据会以字节来的形式交换:
void sweap(char*p1,char*p2,size_t width)//width为单个元素的字节
{
for(int i=0;i<width;i++)//里面会单个单个字节来交换
{
char tem=*p1;
*p1=*p2;
*p2=tem;
p1++;
p2++;
}
}
最后我们只需要定义一个打印的函数
void print(int *p,int sz)
{
for(int i=0;i<sz;i++)
{
printf("%d ",p[i]);
}
}
这就是qsort来排序整形数据的方式
下面是整个函数的代码
#include<stdio.h>
//#include<stdlib.h>
void print(int *p,int sz)
{
for(int i=0;i<sz;i++)
{
printf("%d ",p[i]);
}
}
int compar(const void*p1,const void*p2)
{
return *(int*)p1-*(int*)p2;
}
void sweap(char*p1,char*p2,size_t width)
{
for(int i=0;i<width;i++)
{
char tem=*p1;
*p1=*p2;
*p2=tem;
p1++;
p2++;
}
}
void my_qsort(void*p,size_t sz,size_t width,int (*ptr)(const void*,const void*))
{
int i=0;
for(i=0;i<sz-1;i++)
{
for(int j=0;j<sz-i-1;j++)
{
if(compar((char*)p+j*width,(char*)p+(j+1)*width)>0)
{
sweap((char*)p+j*width,(char*)p+(j+1)*width,width);
}
}
}
}
void test()
{
int arr[10]={3,4,5,2,1,6,7,8,9,0};
int sz=sizeof(arr)/sizeof(arr[0]);
my_qsort(arr,sz,sizeof(arr[0]),compar);
int *p=arr;
print(p,sz);
}
int main()
{
test();
return 0;
}
下面我会给出qsort来通过比较结构体中的char[]来排序的代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct stu
{
char name[20];
int age;
int num;
};
int ptr(const void*p1,const void*p2)
{
return strcmp(((struct stu*)p1)->name,((struct stu*)p2)->name);
}
void print(struct stu *p,int sz)
{
for(int i=0;i<sz;i++)
{
printf("%s %d %d\n",p[i].name,p[i].age,p[i].num);
}
}
void test()
{
struct stu arr[3];
printf("请输入三个人的信息:");
int sz=sizeof(arr)/sizeof(arr[0]);
for(int i=0;i<sz;i++)
{
scanf("%s %d %d",arr[i].name,&arr[i].age,&arr[i].num);
}
qsort(arr,sz,sizeof(arr[0]),ptr);
struct stu *p=arr;
print(p,sz);
}
int main()
{
test();
return 0;
}
其比较部分是通用的,大家可以试着自己改写