sort对类对象进行自定义排序/重载操作符/友元函数/仿函数

我们都知道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有两种参数个数不同的原型,实现自定义排序的方法有四种。实践才是检验整理的唯一标准,建议自己试一试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值