不再造轮子,攻略 STL 中的所有算法

不再造轮子,攻略 STL 中的所有算法

STL 算法概观

1.1 STL 算法总览

  • 质变:指会改变其操作对象的内容
  • *表示不在 STL 标准规格的 SGI 专属算法
  • if in-place 指在同一区间操作

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.2 质变算法 mutating algorithm

STL 算法都作用在迭代器【first, last) 所标识的区间上。

质变算法: 在运算过程中会更改区间内(迭代器所指)的元素内容。

例如: 拷贝,交换,替换,填充,删除, 排列组合,分割, 随机重排,排序等算法,都属于该类。

若将该类算法运用到一个常数区间上,则编译器会给予一大堆错误 信息。

#include "main.h"                                                       
  2 using std::vector;                                                      
  3 int main()
  4 {
   
  5     vector<int> ivec{
   1,2,3,4,5};
  6     sort(ivec.cbegin(), ivec.cend());                                                                                                               
  7     return 0;                                                           
  8 }
  9 

在这里插入图片描述

1.3 非质变算法 nomutating algorithms

非质变算法: 在运算过程中不会改变区间内元素的内容

诸如: 查找,匹配,计数,遍历,比较等算法

如果在这些算法添加一个会改变内容的仿函数, 元素当然会被改变。

1.4 STL 算法的一般形式

  • 所有泛型算法的前两个参数都为一对迭代器,且位前闭后开区间【first, last)
  • 区间必须满足first 累加操作的反复运用,能到达 last,因此需要保证算法能接收的最低程度的迭代器类型。
  • 设置特定操作: STL 算法中大多支持多个版本,拥有自己的缺省行为, 通过外界传递仿函数(functor),以便采用其他策略。 附从 _if 的算法如 find_if 也是一样可以传递仿函数进行对比行为。
  • 具有拷贝版本的算法: 在质变算法中,除了就地修改外,还提供了 copy(另行版本)将修改后的区间序列拷贝到另外的地方,如: replace_copy

数值算法都实现与 numeric 中,其他都实现在 algorithm 中

数值算法

数值算法统一定义在 numeric 中, 我们来介绍如下几种:

        int ia[5] = {
   1, 2, 3, 4, 5};
  6     vector<int> iv(ia, ia+5);
  7     cout << accumulate(iv.begin(), iv.end(), 0) << endl;     
         // 15                                                                                       
  8     cout << accumulate(iv.begin(), iv.end(), 0, minus<int>()) << endl;
         // -13
  9     cout << inner_product(iv.begin(), iv.end(), iv.begin(),10) << endl;
         // 10 + 1*1 + 2*2 .。。。
 10     cout << inner_product(iv.begin(), iv.end(), iv.begin(), 10, minus<int>(), plus<int>());
         // 10 - (1+1) - (2+2) -(3+3)
 11     
 12     ostream_iterator<int> oite(cout, " ");
 13     partial_sum(iv.begin(), iv.end(), oite) ;
         // 1  3  6  10  15
 14     partial_sum(iv.begin(), iv.end(), oite, minus<int>());
 15      // 1  -1  - 4  -8  -13
 16     adjacent_difference(iv.begin(), iv.end(), oite);
        // 1   1   1   1   1
 17     adjacent_difference(iv.begin(), iv.end(), oite, plus<int>());
 18     // 1   3   5  7   9

2.1 accumulate 元素累计算法

  • 将元素按二元仿函数的规则累计操作的结果相加到 init 上。
  • 默认是 1+2+3 ,若位 minus则, 1-2-3.。。
  1 // 版本1
  2 template <class InputIterator, class T>
  3 T accumulate(InputIterator first, InputIterator last, T init) {
    
  4     for(; first != last; ++first) 
  5         init += *first;
  6     return init;
  7 }
  8 //版本2                                                                                                                                             
  9 template <class InputIterator, class T, class BinaryOperation>
 10 T accumulate(InputIterator first, InputIterator last, T init, 
 11              BinaryOperation binary_op) {
   
 12     for(; first != last; ++first)
 13         init = binary_op(init, *first);
 14     return init;
 15 }

2.2 adjacent_difference 相邻元素之间的差额算法

  • 用于计算 【first, last)中相邻元素的差额。
  • 将 *first 赋值给 *result ,并针对 [first+1,last) 内的每个迭代器 i, 将 *i - *(i-1)的值赋值给 *(result + (i - first))
  • 提供二元仿函数的版本是 将 binary_op(*i, *(i-1)) 的运算结果赋值给 *(result+i-first)
   18 template <class InputIterator, class OutputIterator>
   19 OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result) {
   
   20     if(first == last) 
   21         return result;
   22     *result = *first;
   23     typedef typename  std::iterator_traits<InputIterator>::value_type value_type;
   24     value_type value = *first;
   25     while(++first != last) {
   
   26         value_type tmp = *first; //原地操作时会造成问题,因此需要临时量
   27         *++result = tmp - value;
   28         value = tmp;
   29     }
   30     return ++result;
   31 }
   32 template <class InputIterator, class OutputIterator, class BinaryOperation>
   33 OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op) {
   
   34     if(first == last)
   35         return result;
   36     *result = *first;
   37     using value_type = typename std::iterator_traits<InputIterator>::value_type;
   38     value_type val = *first;
   39     while(++first != last) {
   
   40         value_type tmp = *first;
   41         *++result = tmp - val;
   42         val = tmp;
   43     }
   44     return ++result;
   45 }

2.3 inner_product 求两个区间的一般内积(对应元素相乘之后累加一起)

  • 算法 inner_product 能够计算 【first1, last1) 和 【first2, first2+ (last1 - first1))的一般内积,

先将初始结果初始化位 init, 之后针对 【first1 , last1)的每一个迭代器 i, 从头至尾依序执行

result = result +*i) *   *(first2 + (i - first1))
  • 需要提供初始值 init ,为了能在两个区间都为空的情况下有一个明确的值
  • 可提供仿函数取代 operator+ 和 operator*,

先将初始结果初始化为 init, 之后针对【first1, last1) 的每一个迭代器i, 从头到尾依序执行:

 result = bindary_op1(result, bindary_op2(*i,  *(first2 +(i-first1)))
   47 template<class InputIterator1, class InputIterator2, class T>
   48 T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init) {
   
   49     for(; first1 != last1; ++first1, ++first2) {
   
   50         init +=  *first1 * *first2;
   51     }     
   52     return init;
   53 }         
   54           
   55 template<class InputIterator1,class InputIterator2, cl
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值