1. 程式人生 > >C++小點之範型演算法自定義比較函式的五種方法

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 都在該名稱空間之下 。

這裡寫圖片描述

五:過載 < 運算子

#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更好用,你覺得吶??嘻嘻)