前几天在做题的时候遇到了一道关于结构体排序的题目,一开始没怎么注意数据范围,自己写了一个选择排序,直接超时了,最后只能用系统自带的sort来排序,不过也顺便了解到了qsort
,正好和前面的sort
对比一下,因为有时不支持C++,只能用C语言。顺便再介绍一下结构体的排序方式
sort
头文件:algorithm
// default (1)
template <class RandomAccessIterator>
void sort (RandomAccessIterator first, RandomAccessIterator last);
// custom (2)
template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
第一个参数是数组元素的首地址,第二个参数是数组尾地址的下一个地址,第三个参数是你自己定义的比较函数
比如你有一个数组 A[100]
,如果想对他排序的话,直接就sort(A,A + 100)
就可以了,这里默认是升序的,那么如果我想要降序呢?
自定义cmp函数
这时就得用到cmp
函数了,我自己来定义比较规则,比如我想从大到小排序,我可以这么写cmp
函数:
bool cmp(int a,int b)
{
return a > b; //降序排列
//return a < b; 升序排列
}
对结构体排序
结构体是一种复杂数据类型,你自己写的结构体系统是不知道排序规则的,所以只能你自己来写排序规则,一般对于结构体的排序有两种方式
- 重载运算符
- 自定义cmp函数
下面举个例子
struct student
{
int id;
string name;
int grade;
};
这是我的结构体,我想要按照id
排序,如果id相同,则按照姓名排序,如果还相同,则按照成绩排序,排序方式都是升序。
重载运算符
struct student
{
int id;
string name;
int grade;
bool operator < (student next)
{
//这里重载的是 < 运算符,因为系统默认的降序中使用的就是 <
if(this->id != next.id)return this->id < next.id;
if(this->name != next.name)return this->name < next.name;
return this->grade < next.grade;
}
};
自定义cmp函数
bool cmp(student a,student b)
{
if(a.id != b.id)return a.id < b.id;
if(a.name != b.name)return a.name < b.name;
return a.grade < b.grade;
}
上面就是两种自定义比较规则的方式了,这个有个容易蒙的地方:我怎么知道是 <
升序还是 >
升序?这个要记住:小于升序,大于降序
qsort
这个是C语言里面的比较函数,需要头文件 stdlib.h
这是函数原型
void qsort (void* base, size_t num, size_t size,
int (*compar)(const void*,const void*));
函数的参数多的一批,但是没办法,有总比没有强
第一个参数是数组名,第二个参数是元素个数,第三个参数是数据类型的长度,第四个参数是你自己写的比较函数,这个自己写的比较函数需要一个固定的格式
int cmp(const void* a,const void* b)
{
int* m = (int*)a; //如果是char类型的,那么就写成char* m = (char*)a;
int* n = (int*)b;
return *m - * n; //这个是升序
//return *n - *m,这个是降序
}
但是要注意的是,对于浮点型变量来说,这么写是不行的,因为当两个浮点数差距很小的时候,两者之差会被转换为int
类型,那么就是0,等于没比较,所以应该这么写:
int cmp(const void* a,const void* b)
{
double* m = (double*)a;
double* n = (double*)b;
return *m > *n ? 1 : -1; //升序
//return *m < *n ? 1 : -1; 降序
}
这里的cmp是什么意思呢?
返回正数,说明顺序为 b a
返回负数,说明顺序为a b
返回零,说明可以不交换位置
如果我想要升序的话,那么当我传入一个 a 和 b 时,如果 a > b
,那么我就返回一个正值,否则返回负值。
知道了这些我们就可以利用qsort
对结构体进行排序了