zoukankan      html  css  js  c++  java
  • vector中find和find_if的用法 以后再遍历剁手!

    注:转载:https://blog.csdn.net/bobodem/article/details/49386131

    今天郁闷写大作业中。唉。。每次写都tm暴力遍历。有stl你用毛遍历啊。现在记下来。再遍历就剁手吧。(- -!)

    stl包括容器、迭代器和算法:

    容器 用于管理一些相关的数据类型。每种容器都有它的优缺点,不同的容器反映出程序设计的不同需求。容器自身可能由数组或链表实现,或者容器中的每个元素都有特殊的关键值。

    迭代器 用于遍历一个数据集中的每个元素。这些数据集可能是容器或者容器的子集。迭代器的主要优点是它们为任意类型的容器提供一个小巧并且通用(注意通用很重要)的接口。例如,迭代器接口的一个操作是让它依次遍历数据集的每个元素。这个操作是依赖容器的内总部结构独立完成的。迭代器之所以有效是因为容器类提供它自己的迭代器类型来做“正确的事”,容本身的迭代器了解容器的内部结构。

    迭代器的接口几乎相当于普通的指针。让一个迭代器递增只需调用++操作符。使用*操作符可以得到迭代器引用的数据值。因而迭代器可以被任为是一种智能指针。

    算法 被用于处理数据集中的元素。例如它们可以搜索、排序、修改数据或者其他目的。算法使用迭代器,因此,一个算法只需被编写一次就可以用于任意的容器,因为迭代器的接口对所有类型的容器是通用的。这就是find()的位置

    为了给算法更多的扩展性,需要提供一些被算法调用的附属函数。可以使用通用算法去适应非常特别和复杂的需求。你可以提供自己的搜索标准或者特殊的操作去绑定元素。

    STL的概念是将数据和操作独立开来。数据由容器类管理,而操作是由可配置的算法定义。迭代器则是这两个元素之间的线索。它允许任何算法和容器的交互。

    在某种意义上,STL的概念有勃于面向对象编程的初衷:STL将数据和算法分离而非绑定它们。然而,这样做的理由非常重要:原则上,你可以将任何容器同任何算法绑定,得到的结果是STL是非常可扩展的。

    STL的一个标准是它支持任意数据类型。“标准模板库”意味着,所有部分是适应任意类型的模板。STL是通用编程的例子。容器和算法对任意类型和类都是通用的。

    STL甚至提供更多的通用组件。使用 适配器 和函数体,你可以为特定需要补充、限制和配置算法和接口。

    一个find Vector的例子(BAIDU里找的),注意find不属于vector的成员,而存在于算法中,应加上头文件#include <algorithm>:

    #include <vector>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    int main( )
    {
        vector<int> L;
        L.push_back( 1 );
        L.push_back( 2 );
        L.push_back( 3 );
        L.push_back( 4 );
        L.push_back( 5 );
        vector<int>::iterator result = find( L.begin( ), L.end( ), 3 ); //查找3
        if ( result == L.end( ) ) //没找到
            cout << "No" << endl;
        else //找到
            cout << "Yes" << endl;

    }

    貌似这是个简单版,先mark一下,回头补。

    哈哈,正解在此,虽然渣渣从没玩过,不过很好用的样子,妈妈再也不用担心程序效率低了。

    用stl的find方法查找一个包含简单类型的vector中的元素是很简单的,例如

    vector<string> strVec; 

    find(strVec.begin(),strVec.end(),”aa”);

    假如vector包含一个复合类型的对象呢比如

    class A {

    public:

           A(const std::string str,int id)

           {

                    this->str=str; this->id=id;

           } 

    private:

           std::string str; int id;

            };

    这个时候一般的想法是写个函数遍历这个vector,然后进行比较查找。实际上在使用STL的时候,不建议使用循环遍历的查找方法,有几个理由(参加《effictive c++》46条): 效率:泛型算法通常比循环高效。 正确性: 写循环时比调用泛型算法更容易产生错误。 可维护性: 与相应的显式循环相比,泛型算法通常使代码更干净、更直观。

    实际上通过find_if泛型算法可以很优雅的达到期望的效果。

    template<class InputIterator, class Predicate> InputIterator find_if( InputIterator _First, InputIterator _Last, Predicate_Pred );

    这里的最后一个参数可是一个一元谓词,即只带一个参数且返回值限定为bool的函数对象,例如

    bool compare(A& dValue)

    {

          if(dValue.GetStr().compare(“bb”)==0)

                  return true;

          else

                  return false;

    }

    示例:

    vector<A> a;

    A b(“aa”,4);

    A c(“bb”,6);

    A d(“zz”,7);

    a.push_back(b);

    a.push_back(c);

    a.push_back(d);

    vector<A>::iterator t=find_if(a.begin(),a.end(),compare);

    以上函数限定了比较的内容,如果我们想要灵活的自定义比较条件的话要如何做呢,有2个办法,一个是自定义类 ,并重载()操作符号,例如:

    class findx {

    public:

             findx(const string str){test=str;}

             string GetTest() {return test;}

             bool operator()(A& dValue) {

             if(dValue.GetStr().compare(test)==0)

                  return true;

             else

                  return false;

              }

    private: 

              string test;

    };

    比较的时候只要

    vector<A>::iterator t=find_if(a.begin(),a.end(),findx(“33″));

    还有一种方法是使用仿函数和绑定器。仿函数就是类似上面的重载了操作符()的自定义类,或者用struct也可以。因为他定义了操作符“()”,所以能够像函数调用一样在对象名后加上“()”,并传入对应的参数,从而执行相应的功能。这样的类型就是函数对象,从而能作为函数参数传递给find_if。

    下面再说绑定器:

    STL中的绑定器有类绑定器和函数绑定器两种,类绑定器有binder1st和binder2nd,而函数绑定器是bind1st和bind2nd,他们的基本目的都是用于构造一个一元的函数对象。比如这里我们可以利用bind2nd通过绑定二元函数对象中的第二个参数的方式来实现二元谓词向一元谓词的转换。

    struct compare: binary_function<A, string,bool> {

                 bool operator()( A &value, string str) const

                 {

                        if (value.GetStr()== str)

                               return true;

                       else

                               return false;

                  }

    };

    示例:

    vector<A>::iterator t=find_if(a.begin(),a.end(),bind2nd(compare(),”33″));

    无论是用vector的循环还是find_if泛型算法,在性能和代码复杂度上面都有一定得权衡,至于在实际应用中,还是需要具体问题具体分析的。

    以下泛型模板,反正我是没看懂,不知道以后会不会用到。

    现在还是迷糊的,下面是自己在项目中看到的师傅写的一个比较实用的方法:

    template<typename T> bool compare_no(const T* s1 , const T* s2)

    {  

              return strcmp(s1->no, s2->no) == 0;

    }

    template<typename T> bool less_no(const T* s1 , const T* s2)

    {

             return strcmp(s1->no, s2->no) < 0;

    }

    template<typename T> bool compare_id(const T* s1 , const T* s2)

    {

              return s1->id == s2->id;

    }

    template<typename T> bool less_id(const T* s1 , const T* s2)

    {

              return s1->id < s2->id;

    }

    //排序
     std::sort(vct_device.begin(), vct_device.end(), less_id<ST_DEVICE>);
     std::sort(vct_camer.begin(), vct_camer.end(), less_no<ST_CAMERA>);

     //通过编号查找ID

     vector<ST_CAMERA*>::iterator it_cam;
     ST_CAMERA tmp_cam;
     strcpy(tmp_cam.no, "888888");
     it_cam = std::find_if(vct_camer.begin(),vct_camer.end(),bind2nd(ptr_fun(compare_no<ST_CAMERA>), &tmp_cam));
     if (it_cam != vct_camer.end())
          返回值channel = (*it_cam)->channel;

    //通过ID查找编号

     vector<ST_CAMERA*>::iterator it_cam;
     ST_CAMERA tmp_cam;
     int camid = 0;
     tmp_cam.id = 3;
     it_cam = std::find_if(vct_camer_secd.begin(), vct_camer_secd.end(), bind2nd(ptr_fun(compare_id<ST_CAMERA>), &tmp_cam));
     if (it_cam == vct_camer_secd.end())
            返回值strcpy(camera,(*it_cam)->no);

  • 相关阅读:
    ThinkPHP---框架介绍
    (独孤九剑)--cURL
    浅谈Session与Cookie的区别与联系
    (独孤九剑)--会话管理和控制
    PHP数据乱码
    (独孤九剑)---PHP操作MySQL数据库
    错误宝典
    变量、常量、注释、PEP8开发规范、数据类型、Python2和Python3的区别、用户输入、流程控制语句
    什么是编程语言
    CSS
  • 原文地址:https://www.cnblogs.com/wangtingyi/p/8794060.html
Copyright © 2011-2022 走看看