STL与泛型编程<十八>:STL算法之非变动性算法(Nonmodifying algorithm)

1.元素计数(count和count_if)

count声明:

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 ret = 0;
    while (first!=last) 
    {
        if (*first == val) 
        ++ret;
        ++first;
    }
    return ret;
}
/* 可知返回值型别是difference_type,表现迭代器间距的型别 */

count_if声明如下

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; } 

使用如下

int val[] = {1,2,3,4,5,6};
vector<int> col(val,val+6);
int cnt = count(col.begin(),col.end(),4); //1
cnt = count_if(col.begin(),col.end(),bind2nd(greater<int>(),4));//3

2.最小值和最大值(max_element)

max_element声明

template <class ForwardIterator>
ForwardIterator max_element (ForwardIterator first, ForwardIterator last);//默认以operator < 进行比较

template <class ForwardIterator, class Compare>
ForwardIterator max_element (ForwardIterator first, ForwardIterator last, Compare comp);

等效于

template <class ForwardIterator>
ForwardIterator max_element ( ForwardIterator first, ForwardIterator last )
{
    if (first==last)
        return last;
    ForwardIterator largest = first;

    while (++first!=last)
    {
        if (*largest<*first)    // or: if (comp(*largest,*first)) for version (2)
            largest=first;
    }
    return largest;
}

使用如下

#include <iostream> // std::cout
#include <algorithm> // std::min_element, std::max_element

bool myfn(int i, int j) { return i<j; }

struct myclass {
  bool operator() (int i,int j) { return i<j; }
} myobj;

int main () 
{
    int myints[] = {3,7,2,5,6,4,9};

  // using default comparison:
    std::cout << "The smallest element is " << *std::min_element(myints,myints+7) << '\n';
    std::cout << "The largest element is "  << *std::max_element(myints,myints+7) << '\n';

  // using function myfn as comp:
    std::cout << "The smallest element is " << *std::min_element(myints,myints+7,myfn) << '\n';
    std::cout << "The largest element is "  << *std::max_element(myints,myints+7,myfn) << '\n';

  // using object myobj as comp:
    std::cout << "The smallest element is " << *std::min_element(myints,myints+7,myobj) << '\n';
    std::cout << "The largest element is "  << *std::max_element(myints,myints+7,myobj) << '\n';

    return 0;
}

3.搜寻元素(find和find_if)

1.搜寻第一个匹配元素

find声明如下

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;
}

find_if声明如下

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;
}

使用如下

int val[] = {1,2,3,45,6};
vector<int> col(val,val+6);
vector<int>::iterator pos = find(col.begin(),col.end(),45);
if (pos != col.end()) 
{
    //found!
}
pos = find_if(col.begin(),col.end(),bind2nd(greater<int>(),2));

2.搜寻前n个连续匹配值(search_n)

search_n的声明:

template <class ForwardIterator, class Size, class T>
ForwardIterator search_n (ForwardIterator first, ForwardIterator last, Size count, const T& val); //返回第一组“连续count个元素全等于value”的元素位置的第一个元素

template <class ForwardIterator, class Size, class T, class BinaryPredicate>
   ForwardIterator search_n ( ForwardIterator first, ForwardIterator last, Size count, const T& val, BinaryPredicate pred );// 寻找pred(elem,val)为true的,返回意义同上

等效于

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); //first只可能到limit位置

    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;  //not found ,return last 
}

例子

// search_n example
#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'; //2
    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'; // 5
    else
        std::cout << "match not found\n";

    return 0;
}

关于search_n的第二种形式,请看以下调用

pos = seach_n(col.begin(),col.end(),4,3,greater<int>());//以这种方法来搜寻元素和以往的STL算法有些不同,以往的可能如下
pos = seach_n_if(col.begin(),col.end(),4,bind2nd(greater<int>(),3));

3.搜寻第一个子区间(search)

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);

/* 两种形式都返回区间[first1,last1)内和区间[first2,last2)完全吻合的第一个自区间内的第一个元素位置,如果没有找到都返回last1 */

其等效于

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;
}

例子如下

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

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

int main (void) 
{
    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'; //3
    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";//needle2 not found

  return 0;
}

4.搜寻最后一个子区间(find_end)

find_end声明如下

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

template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
ForwardIterator1 find_end (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred);
/* 两种形式都返回[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;
}

例子如下

// find_end example
#include <iostream> // std::cout
#include <algorithm> // std::find_end
#include <vector> // std::vector

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

int main () {
  int myints[] = {1,2,3,4,5,1,2,3,4,5};
  std::vector<int> haystack (myints,myints+10);

  int needle1[] = {1,2,3};

  // using default comparison:
  std::vector<int>::iterator it;
  it = std::find_end (haystack.begin(), haystack.end(), needle1, needle1+3);

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

  int needle2[] = {4,5,1};

  // using predicate comparison:
  it = std::find_end (haystack.begin(), haystack.end(), needle2, needle2+3, myfunction);

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

  return 0;
}

5.搜寻某些元素第一次出现的地点(find_first_of)

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);//pred(*it1,*it2),其中it1是
/* 返回第一个既在[first1,end1)也在[first2,end2)出现的元素的位置(在[first1,end1)总的位置),失败返回last1 */

其等效于

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) 
        {
            if (*it==*first1)          // or: if (pred(*first1*it)) for version (2)
            return first1;
        }
        ++first1;
    }
    return last1;
}

例子如下

// find_first_of example
#include <iostream> // std::cout
#include <algorithm> // std::find_first_of
#include <vector> // std::vector
#include <cctype> // std::tolower

bool comp_case_insensitive (char c1, char c2) {
  return (std::tolower(c1)==std::tolower(c2));
}

int main () 
{
  int mychars[] = {'a','b','c','A','B','C'};
  std::vector<char> haystack (mychars,mychars+6);
  std::vector<char>::iterator it;

  int needle[] = {'A','B','C'};

  // using default comparison:
  it = find_first_of (haystack.begin(), haystack.end(), needle, needle+3);

  if (it!=haystack.end())
    std::cout << "The first match is: " << *it << '\n'; //A

  // using predicate comparison:
  it = find_first_of (haystack.begin(), haystack.end(),
                      needle, needle+3, comp_case_insensitive);

  if (it!=haystack.end())
    std::cout << "The first match is: " << *it << '\n';//a

  return 0;
}

6.搜寻两个连续相等的元素(adjacent_find)

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(*it,*(it+1))

/* 返回第一个“两个连续相等的元素”中的第一个元素位置,失败返回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;
}

使用如下

int val[] = {1,2,3,100,100,5};
vector<int> col(val,val+6);
vector<int>::iterator pos;
pos = adjacent_find(col.begin(),col.end()); //返回第一个100的位置 
pos = adjacent_find(col.begin(),col.end(),greater<int>()); //回第二个100的位置 

区间的比较

1.检验相等性(equal)

equal声明

template <class InputIterator1, class InputIterator2>
bool equal (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2);//判断区间[first1,last1)内的元素是否都和“以first2开头的区间”的元素都相等

template <class InputIterator1, class InputIterator2, class BinaryPredicate>
bool equal (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate pred);//pred(*it1,*it2)

等效于

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;
}

例子如下

// equal algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::equal
#include <vector> // std::vector

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

int main () 
{
  int myints[] = {20,40,60,80,100};               // myints: 20 40 60 80 100
  std::vector<int>myvector (myints,myints+5);     // myvector: 20 40 60 80 100

  // using default comparison:
  if ( std::equal (myvector.begin(), myvector.end(), myints) )
    std::cout << "The contents of both sequences are equal.\n"; //打印这行 
  else
    std::cout << "The contents of both sequences differ.\n";

  myvector[3]=81;                                 // myvector: 20 40 60 81 100

  // using predicate comparison:
  if ( std::equal (myvector.begin(), myvector.end(), myints, mypredicate) )
    std::cout << "The contents of both sequences are equal.\n";
  else
    std::cout << "The contents of both sequences differ.\n";// 打印这行 

  return 0;
}

2. 搜寻第一处不同点(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);//pred(*it1,*it2)
/* 返回区间[first1,end1)和"以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);
}

例子如下

// mismatch algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::mismatch
#include <vector> // std::vector
#include <utility> // std::pair

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

int main () {
  std::vector<int> myvector;
  for (int i=1; i<6; i++) myvector.push_back (i*10); // myvector: 10 20 30 40 50

  int myints[] = {10,20,80,320,1024};                // myints: 10 20 80 320 1024

  std::pair<std::vector<int>::iterator,int*> mypair;

  // using default comparison:
  mypair = std::mismatch (myvector.begin(), myvector.end(), myints);
  std::cout << "First mismatching elements: " << *mypair.first; // 30 
  std::cout << " and " << *mypair.second << '\n';// 80 

  ++mypair.first; 
  ++mypair.second;

  // using predicate comparison:
  mypair = std::mismatch (mypair.first, myvector.end(), mypair.second, mypredicate);
  std::cout << "Second mismatching elements: " << *mypair.first;// 40 
  std::cout << " and " << *mypair.second << '\n';// 320 

  return 0;
}

你可能感兴趣的:(STL与泛型编程<十八>:STL算法之非变动性算法(Nonmodifying algorithm))