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 | 查找满足谓词条件的元素个数 |
一、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;
}
二、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;
}
三、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;
}
四、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;
}
五、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;
}
六、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;
}
七、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;
}
八、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;
}
九、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;
}
十、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;
}