函数简介
头文件: <stdlib.h>;
函数声明:
void qsort( <mark>void * base</mark> , <mark>size_t nitems</mark> , <mark>size_t size</mark> , <mark>int ( * compar) (const void * , const void * )</mark>)
参数:
- base-- 指向要排序的数组的第一个元素的指针。
- nitems-- 由 base 指向的数组中元素的个数。
- size-- 数组中每个元素的大小,以字节为单位。
- compar-- 用来比较两个元素的函数,即函数指针(回调函数)
回调函数:
- 回调函数就是一个通过函数指针调用的函数。如果把函数的指针(地址)作为参数传递
给另一个函数,当这个指针被用来调用其所指向的函数时,就说这是回调函数。
compar参数
- compar参数指向一个比较两个元素的函数。比较函数的原型应该像下面这样。注意两个形参必须是const void *型,同时在调用compar 函数(compar实质为函数指针,这里称它所指向的函数也为compar)时,传入的实参也必须转换成const void *型。在compar函数内部会将const void *型转换成实际类型。
- int compar(const void *p1, const void *p2);
- 如果compar返回值小于0(< 0),那么p1所指向元素会被排在p2所指向元素的左面;
- 如果compar返回值等于0(= 0),那么p1所指向元素与p2所指向元素的顺序不确定;
- 如果compar返回值大于0(> 0),那么p1所指向元素会被排在p2所指向元素的右面。
一、数组排序(整型、double、字符串)
1.参考代码:
#include<stdio.h>
#include<stdlib.h>
#define N 10
int cmp1(const void *a, const void *b)//整型数组
{
int *s1 = (int *)a;
int *s2 = (int *)b;
return *s1 - *s2;
}
int cmp2(const void *a, const void *b)//字符串数组
{
double *s1 = (double *)a;
double *s2 = (double *)b;
return *s1 > *s2 ? 1:-1;
//两个double类型相减会导致精度丢失,无法得出正确的正负值
//所以只能通过比较大小来返回正确的正负值
}
int cmp3(const void *a, const void *b)//整型数组
{
char *s1 = (char *)a;
char *s2 = (char *)b;
return *s1 - *s2;
}
int main()
{
int num1[N] = {9,8,7,6,5,4,3,2,1,0};
qsort(num1 , N , sizeof(int) , cmp1);
double num2[N] = {1.9,1.8,1.7,1.6,1.5,1.4,1.3,1.2,1.1,1.0};
qsort(num2 , N , sizeof(double) , cmp2);
char str[N] = {'j','i','h','g','f','e','d','c','b','a'};
qsort(str , N , sizeof(char) , cmp3);
int i;
printf("整型数组排序:\n");
for(i = 0 ; i < N ; i++)
printf("%d " , num1[i]);
printf("\n");
printf("double数组排序:\n");
for(i = 0 ; i < N ; i++)
printf("%1.2f " , num2[i]);
printf("\n");
printf("字符串数组排序:\n");
for(i = 0 ; i < N ; i++)
printf("%c " , str[i]);
printf("\n");
return 0;
}
2.测试:
二、结构体排序(多级排序)
1.参考代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct student
{
int id;
char name[10];
int grade;
}student;
int cmp1(const void *a, const void *b)//一级排序
{
student *s1 = (student*)a;
student *s2 = (student*)b;
return s1->id - s2->id;
}
int cmp2(const void *a,const void *b)//二级排序
{
student *s1 = (student*)a;
student *s2 = (student*)b;
if(strcmp(s1->name , s2->name) != 0)
return strcmp(s1->name , s2->name);
else
return s1->id - s2->id;
}
int cmp3(const void *a,const void *b)//三级排序
{
student *s1 = (student*)a;
student *s2 = (student*)b;
if(s1->grade != s2->grade)
return s1->grade - s2->grade;
else
{
if(strcmp(s1->name , s2->name) != 0)
return strcmp(s1->name , s2->name);
else
return s1->id - s1->id;
}
}
int main()
{
int i,N,C;
scanf("%d %d",&N,&C);
student *stu;
stu=(student*)malloc(N*sizeof(student));
for(i = 0 ; i < N ; i++)
scanf("%d %s %d" , &stu[i].id , stu[i].name , &stu[i].grade);
switch(C)
{
case 1: qsort(stu, N, sizeof(student), cmp1);break;//一级排序
case 2: qsort(stu, N, sizeof(student), cmp2);break;//二级排序
case 3: qsort(stu, N, sizeof(student), cmp3);break;//三级排序
}
printf("排序结果:\n");
for(i = 0 ; i < N ; i++)
printf("%03d %s %d\n" , stu[i].id , stu[i].name , stu[i].grade);
return 0;
}
2.测试:
结构体体的三级排序测试:
第一级是对学生成绩整体从小到大排序;
第二级是对相同成绩的学生,按照姓名进行排序;
第三级是对相同成绩、姓名的学生,按照学号进行排序;