我们都知道c++库函数sort可以自定义排序,在一般情况下,我们排序的对象都是普通的数据类型比如:int,double等,排序方式无非就是升序和降序,我们可不写比较函数cmp,我们只需在sort的第三参数填入greater<T>
或者less<T>
其中T为模板参数。【<-方法四】
sort函数原型有两种,分别是两个参数和三个参数的函数
template <class RandomAccessIterator>
void sort (RandomAccessIterator first, RandomAccessIterator last);
template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
但是当我们需要对自己写的class或者struct进行自定义排序时,我们要怎么做?
方法一:重载"<"运算符
我们在class
或者struct
里写一个成员函数对运算符<
重载就可以了!但是需要注意的是<
被重载后在该类使用<
都被重载了,而不只是对sort里的<
进行重载,他是对整个类的<
都产生了影响。
必须注意的是可以加const就必须要加const
,否则可能编译出错,这就是const的语法了,本人无法讲清楚,建议去看侯捷的《c++面向高级开发》,平时我们都要养成好多习惯,在class的成员函数中可以加const
都要加上,这样能避免一些不必要的错误。
有人不知道为什么重载<
就可以实现自定义排序?因为sort里面的排序算法里的比较符都是<
,就像你写的冒泡排序:
if(a[i]<a[i+1]) {……交换a[i]和a[i+1]……}//就可以实现降序排序
如果你把这个<
改成>
你就可以实现升序排序了。
方法二:写一个自定义比较的友元函数cmp
因为友元函数不是class的成员函数,我们可以直接调用,并且访问私有的数据。
现在给出方法一、二的样例代码:
#include<bits/stdc++.h>
using namespace std;
class Time{
private:
int hour;
public:
void set(){
cin>>hour;
}
void display(){
cout<<hour<<" "<<endl;
}
bool operator <(const Time b)const //第一个const可不加,后面的必须加 ,规范是都加
{
return hour>b.hour;
}
bool operator > (const Time b)const //如果只重载一个那么没重载的符号无法正常使用
{
return hour< b.hour;
}
//上面两个重载运算符把大于、小于符号改反了
friend bool cmp(Time a,Time b);//所以排序函数尽量定义为友元函数
};
bool cmp(Time a,Time b)//从小到大排序
{
return a.hour<b.hour;
}
vector<Time> e;
int main(){
Time t;
for(int i=0;i<3;i++){
t.set();
e.push_back(t);
}
sort(e.begin(),e.end());//由于重载了<,把小于改为了>,可实现按hour降序排序
//sort(e.begin(),e.end(),cmp);//可以使用
for(int i=0;i<e.size();i++){
e[i].display();
}
if(e[0]<e[1])//实际是>的作用
printf("YES\n");
else
printf("NO\n");
return 0;
}
方法三:仿函数
百度百科:仿函数(functor),就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了。
这个就要class的数据类型为public才可以写了,而struct默认数据成员为public所以我们一般都在struct上使用,并不是说class不能使用是因为class数据是私有的。
下面给出样例代码,其中我把数据成员hour改为了公有!
#include<bits/stdc++.h>
using namespace std;
class Time{
public:
int hour;
void set(){
cin>>hour;
}
void display(){
cout<<hour<<" "<<endl;
}
};
vector<Time> e;
class cmp
{
public:
bool operator () (Time A,Time B) const//不加const也可,但是最好+
{
return A.hour>B.hour;
}
};//这是仿函数,类似:我们在priority_queue 的创建时也可以用仿函数
int main(){
Time t;
for(int i=0;i<3;i++){
t.set();
e.push_back(t);
}
sort(e.begin(),e.end(),cmp());
for(int i=0;i<e.size();i++){
e[i].display();
}
/*if(e[0]<e[1])//没有对该类的'>','<'进行重载无法使用
printf("YES\n");
else
printf("NO\n");*/
return 0;
}
struct的:
struct cmp
{
bool operator () (Time A,Time B)
{
return A.hour>B.hour;
}
};
上面的分析很明白了吧-_-
sort有两种参数个数不同的原型,实现自定义排序的方法有四种。实践才是检验整理的唯一标准,建议自己试一试。