Algorithm-非修改序列操作

本文详细介绍了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容器。

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";
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值