算法库--- <algorithm>中的函数

242 阅读5分钟

1.不修改序列 --- all_of, any_of , none_of

all_of  检查谓词pred是否对范围中所有元素为 true

template <class InputIterator, class UnaryPredicate>
      bool all_of (InputIterator first, InputIterator last, UnaryPredicate pred);

(C++11) pred 既可以是一个函数指针,也可以是一个函数对象, 也可以是lamda表达式。 image.png

any_of 检查谓词pred是否对范围中存在一个元素为 true

template <class InputIterator, class UnaryPredicate>
  bool any_of (InputIterator first, InputIterator last, UnaryPredicate pred);

(C++11) image.png

none_of 检查谓词pred是否对范围中没有元素为 true

template <class InputIterator, class UnaryPredicate>
  bool none_of (InputIterator first, InputIterator last, UnaryPredicate pred);

(C++11) image.png

for_each 应用函数到范围中的元素

template <class InputIterator, class Function>
   Function for_each (InputIterator first, InputIterator last, Function fn);

image.png

find  寻找val首次出现位置( 如果没有,那就返回过尾元迭代器)。

template <class InputIterator, class T>
   InputIterator find (InputIterator first, InputIterator last, const T& val);

(C++11) 寻找首个等于val 的元素 image.png

find_if   到第一个pred返回true的元素位置

template <class InputIterator, class UnaryPredicate>
   InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred);

(C++11) 寻找首个满足特定判别标准pred 的元素 image.png

find_if_not    到第一个pred返回false的元素位置

template <class InputIterator, class UnaryPredicate>
   InputIterator find_if_not (InputIterator first, InputIterator last, UnaryPredicate pred);

image.png (C++11) 寻找首个不满足特定判别标准pred 的元素

find_first_of  现有的数据集合,从某个字典里,找属于字典的第一个元素位置。

//1.用 `operator==` 比较元素。
template <class InputIterator, class ForwardIterator>    
    InputIterator find_first_of (InputIterator first1, InputIterator last1,
                                ForwardIterator first2, ForwardIterator last2); 
template <class InputIterator, class ForwardIterator, class BinaryPredicate>
//2.用 `pred` 比较元素。
    InputIterator find_first_of (InputIterator first1, InputIterator last1,
                                ForwardIterator first2, ForwardIterator last2, 
                                BinaryPredicate pred);

image.png (C++11)

adjacent_find  找到 首对相邻的相同(或满足给定谓词pred的)元素位置

//1.用 `operator==` 比较元素。
template <class ForwardIterator>    
ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last); 

//2.用 `pred` 比较元素。                                                                     
template <class ForwardIterator, class BinaryPredicate>    
ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last, 
                                BinaryPredicate pred);

image.png

count  返回val出现的次数

template <class InputIterator, class T>
  typename iterator_traits<InputIterator>::difference_type
    count (InputIterator first, InputIterator last, const T& val);

image.png

count_if   返回满足谓词pred为真的元素个数

template <class InputIterator, class UnaryPredicate>
  typename iterator_traits<InputIterator>::difference_type
    count_if (InputIterator first, InputIterator last, UnaryPredicate pred);

image.png

mismatch  寻找两个集合的值出现不同的首个位置 ,返回一个 pair,含有两者的迭代器

//1.用 `operator==` 比较元素。
template <class InputIterator1, class InputIterator2>   
pair<InputIterator1, InputIterator2>     mismatch (InputIterator1 first1, InputIterator1 last1, 
                                                InputIterator2 first2); 
//2.用 `pred` 比较元素。
template <class InputIterator1, class InputIterator2, class BinaryPredicate> 
pair<InputIterator1, InputIterator2>     mismatch (InputIterator1 first1, InputIterator1 last1,
                                                InputIterator2 first2, BinaryPredicate pred);

image.png

equal  确定两个元素集合是否相同

//1.用 `operator==` 比较元素。
template <class InputIterator1, class InputIterator2>   
bool equal (InputIterator1 first1, InputIterator1 last1, 
           InputIterator2 first2); 
//2.用 `pred` 比较元素。
template <class InputIterator1, class InputIterator2, class BinaryPredicate>   
bool equal (InputIterator1 first1, InputIterator1 last1, 
           InputIterator2 first2, BinaryPredicate pred);

image.png

is_permutation   判断一个序列是否为另一个序列的排列

//1.用 `operator==` 比较元素。
template <class ForwardIterator1, class ForwardIterator2>    
bool is_permutation (ForwardIterator1 first1, ForwardIterator1 last1,
                    ForwardIterator2 first2);
//2.用 `pred` 比较元素。
template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>    
bool is_permutation (ForwardIterator1 first1, ForwardIterator1 last1, 
                    ForwardIterator2 first2, BinaryPredicate pred);

image.png

search  在[fisrt1,last1)搜索一个[fisrt2,last2) 元素整个出现的位置, 没有整个出现 就返回 last1

//1.用 `operator==` 比较元素。
template <class ForwardIterator1, class ForwardIterator2>    
    ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1,  
                            ForwardIterator2 first2, ForwardIterator2 last2); 
//2.用 `pred` 比较元素。
template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>  
ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1, 
                        ForwardIterator2 first2, ForwardIterator2 last2, 
                        BinaryPredicate pred);

image.png

search_n  在范围中搜索一定量的连续某个元素的副本

//1.用 `operator==` 比较元素。
template <class ForwardIterator, class Size, class T>    
ForwardIterator search_n (ForwardIterator first, ForwardIterator last,
                            Size count, const T& val); 
//2.用 `pred` 比较元素。
template <class ForwardIterator, class Size, class T, class BinaryPredicate>   
ForwardIterator search_n ( ForwardIterator first, ForwardIterator last, 
                            Size count, const T& val, BinaryPredicate pred );

image.png

代码实例

all_of, any_of, none_of

#include <vector>
#include <numeric>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <functional>
 
int main()
{
    std::vector<int> v(10, 2);  
    std::partial_sum(v.cbegin(), v.cend(), v.begin());  
    std::cout << "Among the numbers: ";
    std::copy(v.cbegin(), v.cend(), std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
 
    if (std::all_of(v.cbegin(), v.cend(), [](int i){ return i % 2 == 0; })) {
        std::cout << "All numbers are even\n";
    }
    if (std::none_of(v.cbegin(), v.cend(), std::bind(std::modulus<int>(), 
                                                     std::placeholders::_1, 2))) {
        std::cout << "None of them are odd\n";
    }
    struct DivisibleBy
    {
        const int d;
        DivisibleBy(int n) : d(n) {}
        bool operator()(int n) const { return n % d == 0; }
    };
 
    if (std::any_of(v.cbegin(), v.cend(), DivisibleBy(7))) {
        std::cout << "At least one number is divisible by 7\n";
    }
}

输出:

Among the numbers: 2 4 6 8 10 12 14 16 18 20 
All numbers are even
None of them are odd
At least one number is divisible by 7

概念复习

函数指针

lamda表达式

  • auto f = [](int a) -> int { return a + 1; } ;
  • 另外,lambda 表达式在没有参数列表时,参数列表是可以省略的。返回类型 若是可以自动推导出,也可省略。
  • lambda 表达式还可以通过捕获列表捕获一定范围内的变量:
    • [] 不捕获任何变量。
    • [&] 捕获外部作用域中所有变量,并作为引用在函数体中使用(按引用捕获)。
    • [=] 捕获外部作用域中所有变量,并作为副本在函数体中使用(按捕获)。
    • [=,&foo]捕获外部作用域中所有变量,并按引用捕获 foo 变量。
    • [bar] 捕获 bar 变量,同时不捕获其他变量。
    • [this] 捕获当前类中的 this 指针 ,让 lambda 表达式拥有和当前类成员函数同样的访问权限。如果已经使用了 & 或者 =,就默认添加此选项。捕获 this 的目的是可以在 lamda 中使用当前类的成员函数和成员变量
class A
{
    public:
    int i_ = 0;
    void func(int x, int y)
    {
        // error,没有捕获外部变量, 也没有自己的局部变量,却使用了i_
        auto x1 = []{ return i_; };                    
        auto x2 = [=]{ return i_ + x + y; };           // OK,捕获所有外部变量, by value
        auto x3 = [&]{ return i_ + x + y; };           // OK,捕获所有外部变量, by reference
        auto x4 = [this]{ return i_; };                // OK,捕获this指针
        auto x5 = [this]{ return i_ + x + y; };        // error,没有捕获x、y , 却使用了x、y
        auto x6 = [this, x, y]{ return i_ + x + y; };  // OK,捕获this指针、x、y
        auto x7 = [this]{ return i_++; };              // OK,捕获this指针,并修改成员的值
    }
};
int a = 0, b = 1;
auto f1 = []{ return a; };               // error,没有捕获外部变量, 也没有自己的局部变量,却使用了a
auto f2 = [&]{ return a++; };            // OK,捕获所有外部变量,并对a执行自加运算
auto f3 = [=]{ return a; };              // OK,捕获所有外部变量,并返回a
auto f4 = [=]{ return a++; };            // error,a是以拷贝方式捕获的,无法修改外部的a。
auto f5 = [a]{ return a + b; };          // error,没有捕获变量b
auto f6 = [a, &b]{ return a + (b++); };  // OK,捕获a的值和b的引用,并对b做自加运算
auto f7 = [=, &b]{ return a + (b++); };  // OK,捕获所有外部变量的值和b的引用,并对b做自加运算
  • 一个容易出错的细节是关于 lambda 表达式的延迟调用的:
    • 按值捕获得到的外部变量值是在 lambda 表达式定义时的值。此时所有外部变量均被复制了一份存储在 lambda 表达式变量中
    int a = 0;
    auto f = [=]{ return a; };      // 按值捕获外部变量
    a += 1;                         // a被修改了
    std::cout << f() << std::endl;  // 输出? 仍然是0!