平常写题目时,总要用到排序,以至于自己把冒泡排序和选择排序函数都保存了,需要的时候调用,但是只能用于整形,那么有没有什么函数能实现各个类型的快速排序呢?其实C的库函数里面就自带了。
先看摘要
void qsort( void *base, //待排元素的起始位置
size_t num, //数组的元素个数
size_t width, //一个元素的字节大小
int (*cmp)(const void *e1, const void *e2 ) ); //函数指针 (返回的值 <0 ==0 或者 >0)
↑
// 比较函数 e1 和 e2为待比较的两个元素的地址
标题说了,qsort函数能对多种类型进行比较,那么函数的做作者如何知道我们需要比较的类型呢?最重要的就在于自定义的那个函数。
我们先看一下整形的排序
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int cmp_int(const void* e1, const void* e2)
{
if (*(int*)e1 > *(int*)e2)
return 1;
else if (*(int*)e1 == *(int*)e2)
return 0;
else
return -1;
}
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
//排序为升序
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp_int);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
运行结果为0 1 2 3 4 5 6 7 8 9
有同学可能要问了,不就一个整形排序吗?有必要弄得这么麻烦吗?
先别着急,先把原理弄懂。
int cmp_int(const void* e1, const void* e2)
{
if (*(int*)e1 > *(int*)e2)
//前面提问了
//作者怎么知道我们排序的类型就是通过函数
//void* 可以存放任何类型的指针
//我们排什么类型,就强制转化成什么类型
//比如这里排序整形,就强制转化成int*类型。
return 1;
else if (*(int*)e1 == *(int*)e2)
return 0;
else
return -1;
}
既然我们要返回的值只有三种情况,我们可以简化一下这个函数
int cmp_int(const void* e1, const void* e2)
{
return (*(int*)e1 - *(int*)e2);
}
相信看到这里,你已经对qsort有了初步的了解。
我们再看进阶一点的字符串排序
输入10个等长的字符串,进行从小到大排序,然后输出排序后的10个字符串,使用指针来实现。
###输入格式:
输入十行,每行为一个字符串,字符串中不包含空格。
###输出格式:
输出排序后的字符串。
输入样例:
在这里给出一组输入。例如:
pklnsr
olzxni
rigyqo
pgirjr
jbwgvs
mswgrx
jvrfuo
plmppk
leowfm
jdnuog
输出样例:
在这里给出相应的输出。例如:
jbwgvs
jdnuog
jvrfuo
leowfm
mswgrx
olzxni
pgirjr
pklnsr
plmppk
rigyqo
代码如下
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct str{
char arr[10];
};
int sort1(const void* e1, const void* e2)
{
return strcmp(((struct str*)e1)->arr, ((struct str*)e2)->arr);
}
int main()
{
int i = 0;
struct str arr[10];
for (i = 0; i < 10; i++)
scanf("%s", arr[i].arr);
qsort(arr, 10, sizeof(arr[0]), sort1);
for (i = 0; i < 10; i++)
printf("%s\n", arr[i].arr);
return 0;
}
在这里,我们用结构体存放十个字符串,用qsort函数进行排序,应为我们运用的是结构体,所以就强制转换成结构体类型(struct str*)。
来考考你,记住qsort函数了吗?
qsort(arr, //数组
10, //元素个数
sizeof(arr[0]), //一个元素字节大小
sort1); //比较函数
int sort1(const void* e1, const void* e2)
{
return strcmp(((struct str*)e1)->arr, ((struct str*)e2)->arr);
}
自定义的函数强制转化成我们想要的类型,此处是从小到大排序,如果想要从大到小,只需将return后面的两个数据调换一下位置就行了。
记住这些,我们就可以运用qsort排序了。
接下来看结构体排序
7-2 成绩排序 (10 分)
输入格式:
输入一个正整数n(n<50),下面n行输入n个学生的信息,包括:学号、姓名、成绩。
输出格式:
输出从高到低排序后的学生信息,包括:学号、姓名、成绩。
输入样例:
在这里给出一组输入。例如:
3
101 Zhang 78
102 Wang 91
103 Li 85
输出样例:
在这里给出相应的输出。例如
102 Wang 91
103 Li 85
101 Zhang 78
代码如下
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Student
{
int a;
char name[50];
int score;
};
int compare(const void* e1, const void* e2)
{
return ((struct Student*)e2)->score - ((struct Student*)e1)->score;
}
int main()
{
struct Student stud[100];
int n = 0, i = 0;
scanf("%d", &n);
for (i = 0; i < n; i++)
scanf("%d%s%d", &stud[i].a, &stud[i].name, &stud[i].score);
qsort(stud, n, sizeof(stud[0]), compare);
for (i = 0; i < n; i++)
printf("%d %s %d\n", stud[i].a, stud[i].name, stud[i].score);
return 0;
}
排序的代码只有四行,是不是很简便呢,只要记住格式便可以使用了,多说无用,熟能生巧,快去练习吧。
int compare(const void* e1, const void* e2)
{
return ((struct Student*)e2)->score - ((struct Student*)e1)->score;
}
qsort(stud, n, sizeof(stud[0]), compare);