C++小点之范型算法自定义比较函数的五种方法

文章目录

零:使用STL自带的函数(less与greater)

	vector<int> v{45,2,5,8454,34,68421,5,84,1,5};
	
	sort(v.begin() ,v.end(),less<int>());//从小到大
	sort(v.begin() ,v.end(),greater<int>());///从大到小

一:普通比较函数

假设有一个vector<<\string>>,你的任务是统计长度小于5的string的个数,如果使用count_if 函数的话,代码就是这样:
bool LengthIsLessThanFive(const string& str) {
     return str.length() < 5;    
}
int res=count_if(vec.begin(), vec.end(), LengthIsLessThanFive);

二:函数对象类,也就是仿函数

我们继续沿着上一题增加要求,这里我们要求字符串的长度必须在一个区间,而且这个区间人为指定 ,那么我们就可以写成这样:
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
class fun
{
public:
	explicit fun(const int& l ,const int &h ):low(l),high(h) { }
	bool  operator()(const string &s) const {
		return s.length() > low && s.length() < high ; 
	}
private:
	const  int high ;
	const  int  low  ;
};
int main(void){
   std::vector<string> v{"11","2222222","3","44444444","555","66","777777"} ;//长度分别为 2,7,1,8,3,2,6
   int ll,hh  ;
   cin >> ll >> hh ; // 输入1,6 时,num== 3 。输入2,3,num== 0
   int num = count_if(v.begin(),v.end(),fun(ll,hh)); 
   cout << "num ==" << num  << endl ;  
	return 0 ;
}
这个我们来进行一点小小的总结:
***** 1.仿函数解决了一元或者二元谓词不能传入更多参数的尴尬
***** 2.能存储或者处理更多我们需要的有用信息

三:lambda (其实也是一种函数对象啦)

在这里插入图片描述

既然它也是一种函数对象,那么它就拥有函数对象的特征(解决了一元或者二元谓词不能传入更多参数的尴尬),这里我们还是**要求字符串的长度必须在一个区间,而且这个区间人为指定,并且打印该区间内的单词 . **
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
int main(void){
   std::vector<string> v{"11","2222222","3","44444444","555","66","777777"} ;
   //  长度分别为2,7,1,8,3,2,6
   stable_sort(v.begin() ,v.end() ,[](const string &a ,const string &b){
   		return a.size() < b.size() ;
   }); //先按照字符串长度进行排序

   for_each(v.begin(),v.end() ,[](const string &s ){
   			cout << s << "  ";
   }) ;
   cout << endl ;


 	int ll,hh  ;
   cin >> ll >> hh ; 
   auto  num  = count_if(v.begin(),v.end(),[ll,hh ]( const string &a ) {
   		return a.size() > ll && a.size() < hh  ;
   }); 
   cout << "num ==" << num  << endl ;  

	//找到比  ll 大的第一个字符串
   auto  p1 = find_if(v.begin(),v.end(),[ll]( const string &a ) {
   		return a.size() >  ll  ;
   }); 

   //找到比 hh 大 或者等于 的第一个字符串
   auto  p2 = find_if(v.begin(),v.end(),[hh]( const string &a ) {
       return a.size()  >= hh   ;//注意这里必须是 >=  号
   }); 
   for_each(p1,p2,[](const string &s ){ //打印
   			cout << s << "  ";
   }) ;
   cout << endl ;
	return 0 ;
}

四:使用标准库bind函数

要求和前面一样,自己输入字符串的大小范围,找到有多少个字符串满足要求,输出即可 。
#include<iostream>
#include<vector>
#include<functional>
#include<algorithm>
using namespace std;
//bool fun2(const string &s ,string::size_type &l,string::size_type &h ){ 
bool fun2(const string &s ,string::size_type l,string::size_type h,string::size_type temp){
	return s.size() < h && s.size() > l ;
}
bool fun1(const string &s ,std::string::size_type l ){
	return s.size() < l  ;
}
int main(void) {
    using namespace std::placeholders ;//使用该命名空间,使得书写_1,_2,_n 时不需要书写"std::placeholders::_1 "
	std::vector<string> v{"11","2222222","3","44444444","555","66","777777"} ;//长度分别为 2,7,1,8,3,2,6
	int num1= count_if(v.begin(),v.end() ,bind(fun1,_1,6 ) );
	cout << num1  << endl ;
	cout << "please input the length of the string's range : "   ;
	string::size_type ll,hh ;
	cin >> ll >> hh  ;
	int num2= count_if(v.begin(),v.end() ,bind(fun2,_1,ll,hh,5555 ));
	cout << num2  << endl ; 
}
小结:
1. string::size_type 是一种无符号类型的值,并且能够存放的下任何string对象的大小,是string的size函数返回的变量 。在传参数的时候要注意,如果函数是这样子的:
bool fun2(const string &s ,
string::size_type &l,
string::size_type &h,
string::size_type &temp);
在传参数的时候就必须传入string::size_type 类型的变量,如果传入int类型就会出现比较奇葩的现象。也就是说如果有了size()函数的话就不要再使用int 了啦 !!
2.
bool fun2(const string &s ,
string::size_type temp);
count_if(v.begin(),v.end() ,bind(fun2,_1,ll,hh,5555 ));
_1 参数就是所遍历的这个vector ,后边的参数对应进行绑定即可
3. using namespace std::placeholders; 使用该命名空间,使得书写_1,_2,_n 时不需要书写"std::placeholders::_1 。也就是说_1,_2,_n 都在该命名空间之下 。
4.更多用法,点这里:http://en.cppreference.com/w/cpp/utility/functional/bind

这里写图片描述

五:重载 < 运算符

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std ;
class my_class{
public:
	my_class(const string &temp_name ,const int temp_value ):name(temp_name),value(temp_value){ }
	bool  operator<(const my_class & tt ) const {
		return this->value < tt.value  ;
	}
	string name ;
	int value ;
};
int main(void){
  	my_class a[8]={{"赵",3},{"钱",5},{"宋",1},{"李",7},{"张",6},{"刘",9},{"王",456},{"龙",0}} ;
  	sort(a,a+8);
  	for(int i=0;i< 8 ;i++ )	
  		cout << a[i].name << " : " << a[i].value << endl ;
	return 0 ;
}

总结:

当需要自定义比较函数时,如果以后的操作比较都是固定的,就可以用重载,否则还是用普通函数,仿函数或者bind 函数 。(至于用哪个具体的还是要看个人喜好了。但我个人觉得bind更好用,你觉得呐??嘻嘻)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值