Algorithm
定义了一个函数集合,这些函数专门设计用于元素范围。
范围可以是通过iterator或pointer访问的任何对象序列,例如Array或某些STL容器的实例。
值得注意的是算法通过iterator直接对值进行操作,不会以任何方式影响容器的结构(它不会影响容器的大小或内存分配)。
非修改序列操作
| 函数 | 功能 |
|---|---|
| all_of | 范围内所有元素满足测试条件 |
| any_of | 范围内是否有元素满足测试条件 |
| none_of | 范围内所有元素都不满足测试条件 |
| for_each | 范围for将pred应用于每一个元素 |
| find | 范围查找某个值 |
| find_if | 范围内查找满足pred条件的元素的iterator |
| find_if_not | 范围内查找第一个不满足pred条件的元素的iterator |
| find_end | 范围内查找子序列最后一次出现的位置 |
| find_first_of | 范围内查找第一个属于子序列中的元素的iterator |
| adjacent_find | 求值域内相等的相邻元素 |
| count | 范围内元素出现的个数 |
| count_if | 返回范围内满足条件的元素个数 |
| mismatch | 返回两个range中元素第一次出现不同的位置 |
| equal | 测试两个范围内元素是否相等 |
| is_permutation | 测试一个range是否为另一个range的排列(置换) |
| search | 子序列范围 查找 |
| search_n | 元素范围查找 |
以下这些测试函数均要加上下列几个头文件
#include <array>
#include <algorithm>
#include <string>
std::all_of
对[first,last)的所有元素,如果都满足pred则返回true,或者range为空返回true,否则返回false;
这个模板函数的行为相当于:
//返回的值指示元素是否满足检查条件
template<class InputIterator, class UnaryPredicate>
bool all_of (InputIterator first, InputIterator last, UnaryPredicate pred)
{
while (first!=last) {
if (!pred(*first)) return false;
++first;
}
return true;
}
测试代码:
void test_all_of()
{
//检查数组中元素是否都是奇数
std::array<int, 8> foo = { 3,5,7,9,11,13,17,19 };
if (std::all_of(foo.begin(), foo.end(), [](int val) {return val % 2; }))
cout << "all the elements are odd numbers.\n ";
}
std::any_of
对[first,last)的所有元素,如果存在一个或多个满足pred,则返回true,否则返回 false。
这个模板函数的行为相当于:
template<class InputIterator, class UnaryPredicate>
bool any_of (InputIterator first, InputIterator last, UnaryPredicate pred)
{
while (first!=last) {
//存在一个满足即返回true
if (pred(*first)) return true;
++first;
}
return false;
}
测试代码:
void test_any_of()
{
std::array<int, 8> foo{ 0,1,2,-3,-4,5 };
if (std::any_of(foo.begin(), foo.end(), [](int val) {return val < 0; }))
cout << "数组中存在负数\n";
}
std::none_of
对[first,last)的所有元素,如果所有元素都不满足条件pred,则返回true;或者范围为空也返回true,否则返回false。
这个模板函数的行为等价于:
template<class InputIterator, class UnaryPredicate>
bool none_of (InputIterator first, InputIterator last, UnaryPredicate pred)
{
while (first!=last) {
//存在一个满足pred条件的元素即返回false
if (pred(*first)) return false;
++first;
}
return true;
}
测试代码:
void test_none_of()
{
std::array<int, 6> foo{ 1,2,3,-1,-2,-3 };
if (std::none_of(foo.begin(), foo.end(), [](int val) {return val == 0; }))
cout << "数组中不存在0\n";
}
std::for_each
对[first,last)的所有元素,都将调用函数fn;fn可以是一个函数指针或者一个移动构造函数对象。
这个模板函数的行为等价于:
template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function fn)
{
while (first!=last) {
fn (*first);
++first;
}
return fn; // or, since C++11: return move(fn);
}
测试代码:
void test_for_each()
{
std::array<int, 10> _array;
//assign value to all elements
_array.fill(1);
//return iterator
for_each(_array.begin(), _array.end(), [](int val) {std::cout << val << " "; });
cout << endl;
}
std::find
在范围[first,last)内,如果找到元素值等于val,则返回第一个val元素的iterator,如果没有找到,则返回last。该函数使用operator==将单个元素与val进行比较。
这个模板函数的行为等价于:
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;
}
测试代码:
void test_find()
{
std::array<int, 8> foo{ 1,2,3,4,5,6,7,8 };
if (std::find(foo.begin(), foo.end(), 5) != foo.end())
cout << "找到了元素5\n";
if (std::find(foo.begin(), foo.end(), 10) == foo.end())
cout << "没有找到元素10\n";
}
std::find_if
在[first,last)内查找满足条件pred的元素,如果找到这个的元素,返回第一次出现的元素的iterator,如果不存在则返回last。
这个模板函数的行为等价于:
template<class InputIterator, class UnaryPredicate>
InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred)
{
while (first!=last) {
if (pred(*first)) return first;
++first;
}
return last;
}
测试代码:
void test_find_if()
{
std::array<int, 8>foo{ 1,2,3,4,5,6,7,8 };
auto it = std::find_if(foo.begin(), foo.end(), [](int val) {return (val % 2) == 0; });
if (it != foo.end())
cout << "找到了第一个偶数:" << *it << endl;
}
std::find_if_not
返回[first,last)范围内第一个pred返回false的元素的iterator,如果不存在这样的元素则返回last。
这个模板函数的行为等价于:
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;
}
测试代码:
void test_find_if_not()
{
std::array<int, 8>foo{ 1,2,3,4,5,6,7,8 };
auto it = std::find_if_not(foo.begin(), foo.end(), [](int val) {return (val % 2) == 0; });
if (it != foo.end())
cout << "找到该数组内的第一个奇数是:" << *it << endl;
}
std::find_end
在范围[first1,last1)中查找[first2,last2]定义的序列的最后一次出现,并返回其第一个元素的迭代器,如果没有找到,则返回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;
}
测试代码:
void test_find_end()
{
int myints[] = { 1,2,3,4,5,1,2,3,4,5 };
vector<int>haystack(myints, myints + 10);
int needle1[]{ 1,2,3 };
//使用默认比较器
auto it = std::find_end(haystack.begin(), haystack.end(), needle1, needle1 + 3);
if (it != haystack.end())
cout << "needle1 last found at position " << (it - haystack.begin()) << endl;
//自定义比较器
int needle2[]{ 4,5,1 };
it = std::find_end(haystack.begin(), haystack.end(), needle2, needle2 + 3, [](int left, int right) {return left == right; });
if (it != haystack.end())
cout << "needle1 last found at position " << (it - haystack.begin()) << endl;
}
std::find_first_of
返回指向[first1,last2)中属于[first2,last2)的第一个元素的iterator。
这个模板函数的行为等价于:
template<class InputIterator, class ForwardIterator>
InputIterator find_first_of ( InputIterator first1, InputIterator last1,
ForwardIterator first2, ForwardIterator last2)
{
while (first1!=last1) {
for (ForwardIterator it=first2; it!=last2; ++it) {
//如果 [first1,last1)中存在一个属于[first2,last2)中的元素就返回
if (*it==*first1) // or: if (pred(*it,*first)) for version (2)
return first1;
}
++first1;
}
return last1;
}
测试代码:
void test_find_first_of()
{
int mychars[]{ 'a','b','c','A','B','C' };
//拷贝构造函数(begin,end)
vector<char>haystack(mychars, mychars + 6);
int needle[]{ 'A','B','C' };
//忽略大小写
auto it = std::find_first_of(haystack.begin(), haystack.end(), needle, needle + 3, [](char left, char right) {return tolower(left) == tolower(right); });
if (it != haystack.end())
cout << "the first match is:" << *it << endl; //'a'
it = std::find_first_of(haystack.begin(), haystack.end(), needle, needle + 3);
if (it != haystack.end())
cout << "the first match is:" << *it << endl;//'A'
}
std::adjacent_find
在范围[first,last)中搜索两个连续匹配的元素,并返回搜索到的第一对元素的首元素的iterator,如果没有找到这样的pair,则返回last。
这个模板函数的行为等价于:
template <class ForwardIterator>
ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last)
{
if (first != last)
{
ForwardIterator next=first; ++next;
while (next != last) {
if (*first == *next) // or: if (pred(*first,*next)), for version (2)
return first;
++first; ++next;
}
}
return last;
}
测试代码:
void test_adjacent_find()
{
std::array<int, 8> foo{ 1,2,3,3,4,4,5,6 };
auto it = std::adjacent_find(foo.begin(), foo.end());
if (it != foo.end())
cout << "the first pair of adjacent element are:" << *it << endl;
it = std::adjacent_find(++it, foo.end(), [](int left, int right) {return left == right; });
if (it != foo.end())
cout << "the second pair of adjacent element are:" << *it << endl;
}
std::count
template <class InputIterator, class T>
typename iterator_traits::difference_type count (InputIterator first, InputIterator last, const T& val);
返回[first,last)内所有等于val的元素个数。
这个模板函数的行为等价于:
template <class InputIterator, class T>
typename iterator_traits<InputIterator>::difference_type
count (InputIterator first, InputIterator last, const T& val)
{
//计数,typename iterator_traits<InputIterator>::difference_type是一个signed integral type
typename iterator_traits<InputIterator>::difference_type ret = 0;
while (first!=last) {
if (*first == val) ++ret;
++first;
}
return ret;
}
测试代码:
void test_count()
{
std::array<int, 8> foo{ 1,2,3,3,4,4,5,6 };
cout << "数组中值为3的个数:" << std::count(foo.begin(), foo.end(), 3) << endl;//2
}
std::count_if
template <class InputIterator, class UnaryPredicate>
typename iterator_traits::difference_type count_if (InputIterator first, InputIterator last, UnaryPredicate pred);
返回满足pred条件的元素个数。
这个模板函数行为等价于:
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) {
//满足pred条件
if (pred(*first)) ++ret;
++first;
}
return ret;
}
测试代码:
void test_count_if()
{
std::array<int, 8>foo{ -1,-2,-3,-4,-5,0,1,2 };
int cnt = std::count_if(foo.begin(), foo.end(), [](int val) {return val < 0; });
cout << "这个数组中负数的个数是:" << cnt << endl;//5
}
std::mismatch
template <class InputIterator1, class InputIterator2>
pair<InputIterator1, InputIterator2>
mismatch (InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2);template <class InputIterator1, class InputIterator2, class BinaryPredicate>
pair<InputIterator1, InputIterator2>
mismatch (InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, BinaryPredicate pred);
比较两个范围中的元素,第一个range为[first1,last1),第二个range以first2开始,返回两个序列中第一个不匹配的元素。
该函数返回一对iterator,指向每个range中第一个不匹配的元素。
如果两个range内元素都相等,则返回make_pair(last1,xxxx);第二个参数为第二个range中相对位置元素的iterator。
如果都不相等则返回make_pair(first1,first2);
这个模板函数的行为等价于:
template <class InputIterator1, class InputIterator2>
pair<InputIterator1, InputIterator2>
mismatch (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2 )
{
while ( (first1!=last1) && (*first1==*first2) ) // or: pred(*first1,*first2), for version 2
{ ++first1; ++first2; }
return std::make_pair(first1,first2);
}
测试代码:
void test_mismatch()
{
std::array<int, 5>foo{ 1,2,3,4,5 };
std::array<int, 6>Jack{ 1,2,3,4,5,6 };
std::array<int, 5>Tom{ 1,2,2,3,4 };
auto first_pair = std::mismatch(foo.begin(), foo.end(), Jack.begin());
auto second_pair = std::mismatch(foo.begin(), foo.end(), Tom.begin());
std::array<int, 5> Rafic{ 5,4,3,2,1 };
auto thrid_pair = std::mismatch(foo.begin(), foo.end(), Rafic.begin());
cout << "first_pair:" << "first_pair.first" << "-" << *first_pair.second << endl; //(last1,6)
cout << "second_pair:" << *second_pair.first << "-" << *second_pair.second << endl;//(3,2)
cout << "third_pair:" << *thrid_pair.first << "-" << *thrid_pair.second << endl;//(1,5)
}
std::equal
template <class InputIterator1, class InputIterator2>
bool equal (InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2);template <class InputIterator1, class InputIterator2, class BinaryPredicate>
bool equal (InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, BinaryPredicate pred);
比较[first1,last1)和以first2开始的另一个range的对应位置元素是否相等,如果所有对应位置都相等则返回true,否则返回false。
这个模板函数的行为等价于:
template <class InputIterator1, class InputIterator2>
bool equal ( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2 )
{
while (first1!=last1) {
if (!(*first1 == *first2)) // or: if (!pred(*first1,*first2)), for version 2
return false;
++first1; ++first2;
}
return true;
}
测试代码:
void test_equal()
{
std::array<int, 2>foo{ 1,2 };
std::array<int, 2>Jack{ 1,2 };
std::array<int, 2>Tom{ 2,1 };
bool isSame = std::equal(foo.begin(), foo.end(), Jack.begin());
bool isSame_ = std::equal(foo.begin(), foo.end(), Tom.begin());
if (isSame)
{
cout << "foo equal Jack\n";
}
if (!isSame_)
{
cout << "foo not equal Tom\n";
}
}
std::is_permutation
template <class ForwardIterator1, class ForwardIterator2>
bool is_permutation (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2);template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
bool is_permutation (ForwardIterator1 first1,ForwardIterator1 last1,ForwardIterator2 first2, BinaryPredicate pred);
比较[first1,last1)中的元素和以first2开始的元素,如果两个范围中的所有元素都匹配,即使顺序不同,也返回true,否则返回false。
或者说如果[first1,last1)中的所有元素按任意顺序比较都等于从first2开始的范围内的元素,则为true,否则为false。
该模板函数的行为等价于:
template <class InputIterator1, class InputIterator2>
bool is_permutation (InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2)
{
std::tie (first1,first2) = std::mismatch (first1,last1,first2);
if (first1==last1) return true;
InputIterator2 last2 = first2; std::advance (last2,std::distance(first1,last1));
for (InputIterator1 it1=first1; it1!=last1; ++it1) {
if (std::find(first1,it1,*it1)==it1) {
auto n = std::count (first2,last2,*it1);
if (n==0 || std::count (it1,last1,*it1)!=n) return false;
}
}
return true;
}
测试代码:
void test_is_permutation()
{
std::array<int, 5>foo{ 1,2,3,4,5 };
std::array<int, 5>Jack{ 2,1,4,3,5 };
if (std::is_permutation(foo.begin(), foo.end(), Jack.begin()))
cout << "jack and foo contain the same elements.\n";
}
std::search
// [first1, last1) 用于指定查找范围,[first2, last2) 用于指定要查找的序列
//返回[first1,last1)【序列A】中首次出现[first2,last2)【序列B】范围内的元素的位置。如果没有找到则返回last1,它使用operator==比较两个范围内的元素。
template <class ForwardIterator1, class ForwardIterator2>
ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2);
//子序列[first1,last1)只有在[first2,last2)的所有元素都满足pred时才认为是匹配的template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
ForwardIterator1 search (ForwardIterator1 first1,ForwardIterator1 last1,ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred);
- pred:用于自定义查找规则。该规则实际上是一个包含 2 个参数且返回值类型为 bool 的函数(第一个参数接收 [first1, last1) 范围内的元素,第二个参数接收 [first2, last2) 范围内的元素)。函数定义的形式可以是普通函数,也可以是函数对象。
- 注意,search() 函数的第一种语法格式,其底层是借助 == 运算符实现的。这意味着,如果 [first1, last1] 和 [first2, last2] 区域内的元素为自定义的类对象或结构体变量时,使用该函数之前需要对 == 运算符进行重载。
这个模板函数的行为等价于:
template<class ForwardIterator1, class ForwardIterator2>
ForwardIterator1 search ( ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2)
{
if (first2==last2) return first1; // specified in C++11
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) return first1;
if (it1==last1) return last1;
}
++first1;
}
return last1;
}
测试代码:
void test_search()
{
std::array<int, 5>foo;
for (int i = 0; i < 5; ++i)
foo[i] = i * 10;
int needle[]{ 10,20,30 };
auto it = std::search(foo.begin(), foo.end(), needle, needle + 3);
if (it != foo.end())
cout << "在foo中首次发现needle序列的位置是:" << (it - foo.begin()) << endl; //1
else
cout << "没有在foo中找到needle序列\n";
int needle_[]{ 2,3 };
it = std::search(foo.begin(), foo.end(), needle_, needle_ + 2, [](int left, int right) {return (left / 10) == right; });
if (it != foo.end())
cout << "在foo中首次发现needle_序列的位置是:" << (it - foo.begin()) << endl; //2
else
cout << "没有在foo中找到needle_序列\n";
}
std::search_n
//在[first,last)中查找,连续count个val,如果找到,返回首次出现的位置,否则,返回last,使用operator==来判断
template <class ForwardIterator, class Size, class T>
ForwardIterator search_n (ForwardIterator first, ForwardIterator last, Size count, const T& val);//在[first,last)中查找,连续count个val,如果找到,返回首次出现的位置,否则,返回last,使用pred来判断
template <class ForwardIterator, class Size, class T, class BinaryPredicate>
ForwardIterator search_n ( ForwardIterator first, ForwardIterator last,Size count, const T& val, BinaryPredicate pred );
- pred:用于自定义查找规则。该规则实际上是一个包含 2 个参数且返回值类型为 bool 的函数(第一个参数接收 [first, last) 范围内的元素,第二个参数接收 val)。函数定义的形式可以是普通函数,也可以是函数对象。
这个模板函数的行为等价于:
template<class ForwardIterator, class Size, class T>
ForwardIterator search_n (ForwardIterator first, ForwardIterator last,
Size count, const T& val)
{
ForwardIterator it, limit;
Size i;
limit=first; std::advance(limit,std::distance(first,last)-count);
while (first!=limit)
{
it = first; i=0;
while (*it==val) // or: while (pred(*it,val)) for the pred version
{ ++it; if (++i==count) return first; }
++first;
}
return last;
}
测试代码:
void test_search_n()
{
std::array<int, 5>foo{ 10,10,20,20,20 };
auto it = std::search_n(foo.begin(), foo.end(), 3, 20);
if (it != foo.end())
cout << "foo中首次出现连续3个20的位置是:" << (it - foo.begin()) << endl;
else
cout << "foo中没有出现连续3个20\n";
it = std::search_n(foo.begin(), foo.end(), 3, 2, [](int left, int val) {return (left / 10) == val; });
if (it != foo.end())
cout << "foo中首次出现满足pred的连续3个2的位置是:" << (it - foo.begin()) << endl;
else
cout << "foo中没有出现满足pred连续3个2\n";
}
本文详细介绍了C++标准库中的一系列序列操作算法,如all_of、any_of、none_of用于检查元素条件,for_each遍历并应用函数,find、find_if和find_if_not查找特定元素,find_end和find_first_of搜索子序列,adjacent_find查找相邻重复元素,count和count_if计算元素数量,mismatch比较两个范围,equal和is_permutation检查序列等价和排列,以及search和search_n查找子序列。这些算法适用于迭代器或指针访问的任何对象序列,如数组或STL容器。

8878

被折叠的 条评论
为什么被折叠?



