STL算法之查找

STL算法库中提供的查找相关算法主要有以下几种,查找主要分为2类:

  • 在范围中找元素:find,find_if,find_if_not,find_first_of(在范围中找 出现在另一范围的第一个元素)
  • 在范围中找范围 : find_end,search,search_n(多个连续的数可看成范围)
算法 功能
find 返回第一个等价于给定值的元素的迭代器
find_if 返回第一个使得 一元谓词返回为ture 的元素的迭代器
find_if_not 返回第一个值不满足给定条件(一元谓词返回false)的元素的迭代器。
find_first_of 查找范围 A 中第一个与范围 B 中任一元素满足条件的元素的位置。
find_end 在范围A中找 范围B最后一次出现的位置
search 在范围A中 找 范围B 第一次出现的位置
search_n 在范围中 找连续出现的给定值
adjacent_find 查找满足条件的 相邻元素
count 查找等于给定值的元素个数
count_if 查找满足谓词条件的元素个数


1 find

函数原型:

template <class InputIterator, class T>
   InputIterator find (InputIterator first, InputIterator last, const T& val);
  • 在 [first,last)范围中查找第一个等于val的值,如果找到这返回该值的迭代器,否则返回迭代器last。
  • 该函数使用operator== 运算符进行比较。所以对于自定义类型(类,结构体),需要重载==运算符。
    函数的实现等价于:
template<class InputIterator, class T>
  InputIterator find (InputIterator first, InputIterator last, const T& val)
{
  while (first!=last) {
    if (*first==val) return first;
    ++first;
  }
  return last;
}


示例1:
C++内置类型的查找。

#include <iostream> // std::cout
#include <algorithm> // std::find
#include <vector> // std::vector

int main () {
  // using std::find with array and pointer:
  int myints[] = { 10, 20, 30, 40 };
  int * p;

  p = std::find(myints, myints+4, 30);
  //p = std::find(std::begin(myints),std::end(myints),30);
  if (p != myints+4)
    std::cout << "Element found in myints: " << *p << '\n';
  else
    std::cout << "Element not found in myints\n";

  // using std::find with vector and iterator:
  std::vector<int> myvector(myints,myints+4);
  std::vector<int>::iterator it;

  it = find (myvector.begin(), myvector.end(), 30);
  if (it != myvector.end())
    std::cout << "Element found in myvector: " << *it << '\n';
  else
    std::cout << "Element not found in myvector\n";

  return 0;
}

示例2:
自定义类型的查找。

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

class Node
{
public:
    int val;

    Node(int _v)
    {
        val = _v;
    }

    friend bool operator==(const Node&a,const Node&b)
    {
        return a.val == b.val;
    }
};

int main()
{
    vector<Node> nodeVec;

    nodeVec.push_back(Node(10));
    nodeVec.push_back(Node(5));
    nodeVec.push_back(Node(18));
    nodeVec.push_back(Node(112));
    nodeVec.push_back(Node(24));

    vector<Node>::iterator it = find(nodeVec.begin(),nodeVec.end(),Node(112));

    if( it != nodeVec.end() )
        cout << "数组中的第"<<it-nodeVec.begin()<<"个" <<endl;

    return 0;
}


2 find_if

函数原型:

template <class InputIterator, class UnaryPredicate>
   InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred);
  • 在[first,last)中查找第一个使得pred返回true的元素迭代器。如果没有找到,这返回迭代器last。
  • 条件由 一元谓词函数 给出。
    该函数等价于:
template<class _InIt,
    class _Pr> inline
    _InIt _Find_if(_InIt _First, _InIt _Last, _Pr _Pred)
    {    // find first satisfying _Pred
        for (; _First != _Last; ++_First)
            if (_Pred(*_First))
                break;
        return (_First);
    }

示例3:

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

class Node
{
public:
    int val;

    Node(int _v)
    {
        val = _v;
    }

};

int main()
{
    vector<Node> nodeVec;

    nodeVec.push_back(Node(10));
    nodeVec.push_back(Node(5));
    nodeVec.push_back(Node(18));
    nodeVec.push_back(Node(112));
    nodeVec.push_back(Node(24));

    vector<Node>::iterator it = find_if(nodeVec.begin(),nodeVec.end(),[](Node&a){
        if( a.val == 112 )
            return true;

        return false;
    });

    if( it != nodeVec.end() )
        cout << "数组中的第"<<it-nodeVec.begin()<<"个" <<endl;

    return 0;
}


3 find_if_not

函数原型:

template <class InputIterator, class UnaryPredicate>
   InputIterator find_if_not (InputIterator first, InputIterator last, UnaryPredicate pred);
  • 跟find_if刚好相反。find_if_not是要找到第一个使得pred返回false的元素。
    该函数等价于:
template<class InputIterator, class UnaryPredicate>
  InputIterator find_if_not (InputIterator first, InputIterator last, UnaryPredicate pred)
{
  while (first!=last) {
    if (!pred(*first)) return first;
    ++first;
  }
  return last;
}


4 find_first_of

函数原型:

template <class ForwardIterator1, class ForwardIterator2>
   ForwardIterator1 find_first_of (ForwardIterator1 first1, ForwardIterator1 last1,
                                   ForwardIterator2 first2, ForwardIterator2 last2);

template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
   ForwardIterator1 find_first_of (ForwardIterator1 first1, ForwardIterator1 last1,
                                   ForwardIterator2 first2, ForwardIterator2 last2,
                                   BinaryPredicate pred);
  • 默认在范围1中查找,第一个与范围2中任一元素相等的元素。如果范围1中的某个元素,在范围2中找到跟它相等的元素,则返回范围1中的这个元素的迭代器。
    该函数等价于:
template<class _FwdIt1,
    class _FwdIt2,
    class _Pr> inline
    _FwdIt1 _Find_first_of(_FwdIt1 _First1, _FwdIt1 _Last1,
        _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred)
    {    // look for one of [_First2, _Last2) satisfying _Pred with element
        for (; _First1 != _Last1; ++_First1)
            for (_FwdIt2 _Mid2 = _First2; _Mid2 != _Last2; ++_Mid2)
                if (_Pred(*_First1, *_Mid2))
                    return (_First1);
        return (_First1);
    }

示例4:

#include <iostream>
#include <algorithm>
#include <vector>

#define CLASSFOO_VECTOR(type, name, ...) \
static const type name##_a[] = __VA_ARGS__; \
std::vector<type> name(name##_a, name##_a + sizeof(name##_a) / sizeof(*name##_a))

namespace ClassFoo{
    bool IfEqual(int m, int n) {
        return (m == n);
    }
    void FindFirstOf_1() {
        CLASSFOO_VECTOR(int, BigVector, { 8, 23, 5, 6, 7, 29, 0, 5, 6, 7, 1, 1 });
        CLASSFOO_VECTOR(int, SmallVector, { 18, 9, 123, 66, 5, 6, 7 });
        // 等价比较
        std::vector<int>::iterator it = std::find_first_of(
            std::begin(BigVector),
            std::end(BigVector),
            std::begin(SmallVector),
            std::end(SmallVector));

        if (it != std::end(BigVector)) {
            std::cout << "找到: " << *it << '\n';
            std::cout << "前一个元素是: " << *(it - 1) << '\n';
        }

        // 自定谓词比较
        it = std::find_first_of(
            std::begin(BigVector),
            std::end(BigVector),
            std::begin(SmallVector),
            std::end(SmallVector),
            IfEqual);

        if (it != std::end(BigVector)) {
            std::cout << "找到: " << *it << '\n';
            std::cout << "前一个元素是: " << *(it - 1) << '\n';
        }

    }
}

int main()
{
    ClassFoo::FindFirstOf_1();

    return 0;
}


5 find_end

  • 在范围1中,找到范围2最后一次出现的位置。如果找到,则返回元素的迭代器。如果用集合论的语言来描述,即使首先,F2 ∈ F1,然后再找F1中最靠后的F2。
  • 举例说明:假设F1= 【8, 23, 5, 6, 7, 29, 0, 5, 6, 7, 1, 1 】,F2 =【 5, 6, 7】,那么显然F2 ∈ F1,且F2在F1中最后一次出现是0后面的一个位置。如果F2 = 【5,6,7,9】,则F2 !∈ F1,则返回last1。

该函数等价于:

template<class ForwardIterator1, class ForwardIterator2>
  ForwardIterator1 find_end (ForwardIterator1 first1, ForwardIterator1 last1,
                             ForwardIterator2 first2, ForwardIterator2 last2)
{
  if (first2==last2) return last1;  // specified in C++11

  ForwardIterator1 ret = last1;

  while (first1!=last1)
  {
    ForwardIterator1 it1 = first1;
    ForwardIterator2 it2 = first2;
    while (*it1==*it2) {    // or: while (pred(*it1,*it2)) for version (2)
        ++it1; ++it2;
        if (it2==last2) { ret=first1; break; }
        if (it1==last1) return ret;
    }
    ++first1;
  }
  return ret;
}

示例5:

#include <iostream>
#include <algorithm>
#include <vector>

#define CLASSFOO_VECTOR(type, name, ...) \
static const type name##_a[] = __VA_ARGS__; \
std::vector<type> name(name##_a, name##_a + sizeof(name##_a) / sizeof(*name##_a))

namespace ClassFoo{
    bool IfEqual(int m, int n) {
        return (m == n);
    }
    void FindEnd_1() {
        CLASSFOO_VECTOR(int, BigVector, { 8, 23, 5, 6, 7, 29, 0, 5, 6, 7, 1, 1 });
        CLASSFOO_VECTOR(int, SmallVector, { 5, 6, 7}); //换成{5,6,7,9},则未找到

        // 等价比较
        std::vector<int>::iterator it = std::find_end(
            std::begin(BigVector),
            std::end(BigVector),
            std::begin(SmallVector),
            std::end(SmallVector));
        if (it != std::end(BigVector)) {
            std::cout << "找到: " << *it << '\n';
            std::cout << "前一个元素是: " << *(it - 1) << '\n';
        }
        // 自定谓词比较
        it = std::find_end(
            std::begin(BigVector),
            std::end(BigVector),
            std::begin(SmallVector),
            std::end(SmallVector),
            IfEqual);
        if (it != std::end(BigVector)) {
            std::cout << "找到: " << *it << '\n';
            std::cout << "前一个元素是: " << *(it - 1) << '\n';
        }
    }
}
int main()
{
    ClassFoo::FindEnd_1();
    return 0;
}


6 search

函数原型:

template <class ForwardIterator1, class ForwardIterator2>
   ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1,
                            ForwardIterator2 first2, ForwardIterator2 last2);

template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
   ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1,
                            ForwardIterator2 first2, ForwardIterator2 last2,
                            BinaryPredicate pred);
  • 含义刚好与find_end相反。search是要在F1中找到F2第一次出现的位置。

示例6:

#include <iostream> // std::cout
#include <algorithm> // std::search
#include <vector> // std::vector

bool mypredicate (int i, int j) {
  return (i==j);
}

int main () {
  std::vector<int> haystack;

  // set some values: haystack: 10 20 30 40 50 60 70 80 90
  for (int i=1; i<10; i++) 
      haystack.push_back(i*10);

  // using default comparison:
  int needle1[] = {40,50,60,70};
  std::vector<int>::iterator it;
  it = std::search (haystack.begin(), haystack.end(), needle1, needle1+4);

  if (it!=haystack.end())
    std::cout << "needle1 found at position " << (it-haystack.begin()) << '\n';
  else
    std::cout << "needle1 not found\n";

  // using predicate comparison:
  int needle2[] = {20,30,50};
  it = std::search (haystack.begin(), haystack.end(), needle2, needle2+3, mypredicate);

  if (it!=haystack.end())
    std::cout << "needle2 found at position " << (it-haystack.begin()) << '\n';
  else
    std::cout << "needle2 not found\n";

  return 0;
}


7 search_n

函数原型:

template <class ForwardIterator, class Size, class T>
   ForwardIterator search_n (ForwardIterator first, ForwardIterator last,
                             Size count, const T& val);
template <class ForwardIterator, class Size, class T, class BinaryPredicate>
   ForwardIterator search_n ( ForwardIterator first, ForwardIterator last,
                              Size count, const T& val, BinaryPredicate pred );
  • 在[first,last)中找val出现了count次的位置,返回迭代器。默认的二元谓词使用==运算符。

示例7:

#include <iostream> // std::cout
#include <algorithm> // std::search_n
#include <vector> // std::vector

bool mypredicate (int i, int j) {
  return (i==j);
}

int main () {
  int myints[]={10,20,30,30,20,10,10,20};
  std::vector<int> myvector (myints,myints+8);

  std::vector<int>::iterator it;

  // using default comparison:
  it = std::search_n (myvector.begin(), myvector.end(), 2, 30);

  if (it!=myvector.end())
    std::cout << "two 30s found at position " << (it-myvector.begin()) << '\n';
  else
    std::cout << "match not found\n";

  // using predicate comparison:
  it = std::search_n (myvector.begin(), myvector.end(), 2, 10, mypredicate);

  if (it!=myvector.end())
    std::cout << "two 10s found at position " << int(it-myvector.begin()) << '\n';
  else
    std::cout << "match not found\n";

  return 0;
}


8 adjacent_find

函数原型:

template <class ForwardIterator>
    ForwardIterator adjacent_find (ForwardIterator first,
​                                   ForwardIterator last);    
template <class ForwardIterator, class BinaryPredicate>
    ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last,
                                   BinaryPredicate pred);
  • 在范围内 找一对相邻元素,该队相邻元素满足Pred(使得pred返回true)。
    该函数等价于:
template<class _FwdIt,
    class _Pr> inline
    _FwdIt _Adjacent_find(_FwdIt _First, _FwdIt _Last, _Pr _Pred)
    {    // find first satisfying _Pred with successor
        if (_First != _Last)
            for (_FwdIt _Firstb; (_Firstb = _First), ++_First != _Last; )
                if (_Pred(*_Firstb, *_First))
                    return (_Firstb);
        return (_Last);
    }

示例8:

#include <iostream>
#include <algorithm>
#include <vector>

#define CLASSFOO_VECTOR(type, name, ...) \
static const type name##_a[] = __VA_ARGS__; \
std::vector<type> name(name##_a, name##_a + sizeof(name##_a) / sizeof(*name##_a))

namespace ClassFoo{
        bool Differ2(int m, int n) {//相邻元素相差2
        return (m - n) == 2 || (n-m) == 2;
    }
    void AdjacentFind_1() {
        CLASSFOO_VECTOR(int, BigVector, { 8, 23, 5, 5, 7, 29, 0, 7, 7, 7, 1, 1 });
        // 等价比较
        std::vector<int>::iterator it = std::adjacent_find(
            std::begin(BigVector),
            std::end(BigVector));
        if (it != std::end(BigVector)) {
            std::cout << "找到: " << *it << '\n';
            std::cout << "前一个元素是: " << *(it - 1) << '\n';
        }
        // 自定谓词比较
        it = std::adjacent_find(
            std::begin(BigVector),
            std::end(BigVector),
            Differ2);
        if (it != std::end(BigVector)) {
            std::cout << "找到: " << *it << '\n';
            std::cout << "前一个元素是: " << *(it - 1) << '\n';
        }
    }
}
int main()
{
    ClassFoo::AdjacentFind_1();
    return 0;
}


9 count

函数原型:

template <class InputIterator, class T>
    typename iterator_traits<InputIterator>::difference_type
​        count (InputIterator first, InputIterator last, const T& val);
  • 在范围中,查找与给定值val相等的元素个数。
    函数等价于:
template<class InputIterator, class OutputIterator>
  OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
{
  while (first!=last) {
    *result = *first;
    ++result; ++first;
  }
 return result;
}


10 count_if

函数原型:

template <class InputIterator, class UnaryPredicate>
  typename iterator_traits<InputIterator>::difference_type
    count_if (InputIterator first, InputIterator last, UnaryPredicate pred);
  • 在范围中查找,使得pred为true的元素个数。
    函数等价于:
template <class InputIterator, class UnaryPredicate>
  typename iterator_traits<InputIterator>::difference_type
    count_if (InputIterator first, InputIterator last, UnaryPredicate pred)
{
  typename iterator_traits<InputIterator>::difference_type ret = 0;
  while (first!=last) {
    if (pred(*first)) ++ret; ++first; } return ret; }

示例9:

#include <iostream> // std::cout
#include <algorithm> // std::count_if
#include <vector> // std::vector

bool IsOdd (int i) { return ((i%2)==1); }

int main () {
  std::vector<int> myvector;
  for (int i=1; i<10; i++) myvector.push_back(i); // myvector: 1 2 3 4 5 6 7 8 9

  int mycount = count_if (myvector.begin(), myvector.end(), IsOdd);
  std::cout << "myvector contains " << mycount  << " odd values.\n";

  return 0;
}

你可能感兴趣的:(STL算法之查找)