find_if

 

find_if 算法的定义如下:

template<class InputIterator, class T, class Predicate> inline
   InputIterator find_if(
   InputIterator First,
      InputIterator Last,
      Predicate Predicate
   )

  它和find算法很类似返回的是找到元素的佚代器。它的第三个参数是一个函数

指针(function pointer)或函数对像(object functional)如果是函数对像,它的

定义可以是这样。

template <class T>
class fun
{
public:
bool operator()(const T &a)const
{
        if(a > 10)
               return true;
}
};

这里实现了一个找出大于30的元素(当然元素不一不是int型的)这里是一个小例子


#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
#include "time.h"
using namespace std;


int _rand()
{
return rand()%100;
}

template <class T>
class fun
{
public:
bool operator()(const T &a)const
{
        return a>30;
}
};

 
int main(int argc, char* argv[])
{
srand(time(NULL));
vector<int> vec(16);
generate(vec.begin(),vec.end(),_rand);
copy(vec.begin(),vec.end(),ostream_iterator<int>(cout," "));
cout << endl; 
vector<int>::iterator itr =vec.begin();

while(itr != vec.end())
{
        itr = find_if(itr,vec.end(),fun<int>());
        if(itr != vec.end())
        {
               cout <<*itr << " ";
               itr++;
        }
}
return 0;
}

但是,如果我们要比较的数是一个在运行时改变的数,比如,第一次要找大去30

的,第二次要找大于35的,这如何时实呢?对,binder2nd()!
它是一个模版类定义在<functional>头文件里。

template<class Operation>
   class binder2nd : public unary_function <
         typename Operation::first_argument_type,
         typename Operation::result_type>
   {
public:
   typedef typename Operation::first_argument_type argument_type;
   typedef typename Operation::result_type result_type;
   binder2nd(
      const Operation& _Func,
      const typename Operation::second_argument_type& _Right
   );
   result_type operator()(
      const argument_type& _Left
   ) const;
   result_type operator()(
   argument_type& _Left
   ) const;
protected:
   Operation op;
   typename Operation::second_argument_type value;
   };
怎么样,看晕了吧?简单说下_Func是要绑定的函数对象,_Right是要绑定的二原

函数的第二个参数。那第一个参数呢?是留给find_if用的。这个函数对象从

binary_function派生出来的,我们看看看binary_function的定义:

template<class Arg1, class Arg2, class Result>
   struct binary_function {
      typedef Arg1 first_argument_type;
      typedef Arg2 second_argument_type;
      typedef Result result_type;
   };
它是一个用模版定义的类,用来对函数对象提供C++标准模版库的支持,

first_argument_type 表示第一个参数类型,second_argument_type 表示第二个

参数类型result_type表示返回值类型。C++库的函数对象都是从这个类派生出来

的。

说了这么多怎么用它呢:我还是给个例子吧!功能和上面的差不多,找出大于30

的数。看好了!


#include "stdafx.h"
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

 

#include "time.h"
using namespace std;

template<class T>
class fun: public binary_function<T, T, bool>
{
public:
  result_type operator() ( const first_argument_type a,const

second_argument_type b ) const
  {
         return a>b;
  }
}; 

 

int _rand()
{
  return rand()%100;

int main(int argc, char* argv[])
{
  srand(time(NULL));
  vector<int> vec(16);
  generate(vec.begin(),vec.end(),_rand);
  copy(vec.begin(),vec.end(),ostream_iterator<int>(cout," "));
  cout << endl; 
  vector<int>::iterator itr =vec.begin();
  while(itr != vec.end())
  {
         itr = find_if(itr,vec.end(),binder2nd<fun<int> >(fun<int>

(),30));
         if(itr != vec.end())
         {
                cout <<*itr << " ";
                itr++;
         }
  }
  return 0;
}

 
------------------------------------------------------------------
class my_equal_to
{
public:
    my_equal_to()
    {
        pt = CPoint3D(0, 0, 0);
    }
    my_equal_to(CPoint3D pt1) {pt = pt1;}

    bool operator () (const CPoint3D &point)
    {
        return point == pt;
    }
public:
    CPoint3D pt;
};


int main(int argc, char* argv[])
{
    vector<CPoint3D> vectPtArray;
    vectPtArray.push_back(CPoint3D(1.0, 1.0, 1.0));
    vectPtArray.push_back(CPoint3D(1.0, 2.0, 1.0));
    vectPtArray.push_back(CPoint3D(1.0, 1.0, 3.0));
    vectPtArray.push_back(CPoint3D(1.0, 1.0, 4.0));
    vectPtArray.push_back(CPoint3D(1.0, 1.0, 6.0));

    CPoint3D pt(1.0, 1.0, 6.0);
    vector<CPoint3D>::iterator it =  find_if(vectPtArray.begin(), vectPtArray.end(), my_equal_to(pt));
    pt = CPoint3D(1.0, 2.0, 1.0);
    vector<CPoint3D>::iterator it1 =  find(vectPtArray.begin(), vectPtArray.end(), pt);
    if (it != vectPtArray.end())
    {
        cout<<"("<<(*it).x<<","<<(*it).y<<","<<(*it).z<<")\n";
    }
    if (it1 != vectPtArray.end())
    {
        cout<<"("<<(*it).x<<","<<(*it).y<<","<<(*it).z<<")\n";
    }
    
    return 0;
}
 
---------------------------------------------------------

对map使用find_if

Scott Meyers在《STL高效编程》中强调使用STL自带的算法,在遍历查找容器数据结构时,使用find,find_if要比自己编写的for循环效率要高,这是不错的。我使用find_if的另外一个原因是,如果有现成的,就尽量使用。其实,为给find_if写个谓词函数费的功夫要比直接写个for循环可多多了,之所以走费劲的路,就是要用现成的模式,这应该是程序员的偏执吧。

map结构定义如下:
map<pair<int, int>, Module *> Mmap;
typedef Mmap:iterator MmapIt;

现在要编写一个查找Mmap结构的函数,如果自己写for循环,是这个样子:
Mmap mmap;
Module *lookup_by_first_1st(int val){
      MmapIt mit;
      for (mit = mmap.begin(); mit != mmap.end(); ++mit)
              if ((val >= (*mit).first.first) && ((*mit).first.first) + (*mit).first.second)))
                      return (*mit).second;
              return 0;
}

不管查找原则是什么,这样写很省事。如果要使用STL的find_if,应该是这个样子:
Module *lookup_by_first_2nd(int val){
      MmapIt mit;
      mit = find_if(mmap.begin(), mmap.end(), bind2nd(Access_hit(), val));
      if (mit != mmap.end())
                      return (*mit).second;
              return 0;
}

其中,Access_hit()是个二元谓词函数,它接受的第二个自变量是val, 那么第一个自变量是什么呢?
这个问题的答案对于STL新的使用者来说,其回答也许不是C++STL所规定的那样,是容器的值类型,在这里就是pair<pair<int, int>, Module *>, 而是更自然的MmapIt!当然,可能有些人的自然反应正好相反,和C++的标准一样,而我呢,属于那另外的,直觉总是与正解相反的人群。

也许,真的是直觉有问题:毕竟那个谓词函数所使用的应该是值,基本上没有可能性会使用iterator,所以标准的规定也是自然的。对于for_each用到的函数,传递的参数也是值类型,所以,也就没什么好抱怨的。只是稍稍有点怪异的地方是:map的值类型是个pair,所以,要保持一致的话,Mmap的写法应该是这样:

map<pair<pair<int, int>, Module *>> Mmap;

但是,这么写太怪异了,所以,还是遵从C++的规定,这样同时也就遵循了最简原则,只是要记住的东西多一点而已。不过,东记一点,西记一点,加起来就是可观的记忆负担。这就是C++的特点:虽然优美,但是复杂。要记的东西太多,因为表记上不一致的地方就需要规定来解套,或者在用强类型和祈使句式表达起来困难的场合,就得使用新发明的语法,比如模板。C++的这些困难,在动态函数式语言如Lisp那里,根本就不是问题。

把函数写完整,Access_hit的定义是这样:
struct Access_hit : public std::binary_function<pair<pair<int, int>, Module *>, const int, bool> {
      bool operator()(pair<pair<int, int>, Module *> bsp, const int val) const {
              if ((val >= bsp.first.first) && (bsp.first.first) + bsp.first.second)))
                      return true;
              return false;
      }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值