函数简介

简介来源于百度百科

头文件: <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.测试:

结构体体的三级排序测试:
第一级是对学生成绩整体从小到大排序;
第二级是对相同成绩的学生,按照姓名进行排序;
第三级是对相同成绩、姓名的学生,按照学号进行排序;