不再造轮子,攻略 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, class T, 
   56     class BinaryOperation1, class BinaryOperation2> 
   57 T inner_product(InputIterator1 first1, InputIterator1 last1,InputIterator2 first2, T init,
   58                 BinaryOperation1 binary_op1, BinaryOperation2 binary_op2) {
   59     for(; first1 != last1; ++first1, ++first2) {
   60         init = binary_op1(init, binary_op2(first1, first2));
   61     }     
   62     return init;
   63 }                                                                                                                                                 
   64 

2.4 partial_sum 计算局部总和

  • 运算中的局部总和 sum 首先初始化为 *first, 然后赋值给 *result, 之后随着first 的遍历sum = sum + *first, 之后赋值给 *(result + i - first)
  • 带 二元仿函数的即 sum = binary_op(sum, *first)
   65 template<class InputIterator, class OutputIterator>
   66 OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result) {
   67     if(first == last)  
   68         return result; 
   69     using value_type = typename std::iterator_traits<InputIterator>::value_type;
   70     value_type sum = *first;
   71     while(++first != last) {
   72         sum += *first; 
   73         *++result = sum;
   74     }                  
   75     return ++result;   
   76 }                      
   77 template<class InputIterator, class OutputIterator, class BinaryOperation>
   78 OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op) {
   79     if(first == last)  
   80         return result; 
   81     using value_type = typename std::iterator_traits<InputIterator>::value_type;
   82     value_type sum = *first;
   83     while(++first != last) {
   84         sum = binary_op(sum, *first);
   85         *++result = sum;
   86     }
   87     return ++result;
   88 }

2.5 power

该算法不再标准之内,用来计算 某个数的 n 幂次方,可以指定其数的某种运算

x的n次方 = x 的 n/2 次方 * x 的n/2次方 。(n 为奇数须再次乘上 x)

      template <class T, class Integer, class MonoidOperation>                                                                             
   92 T power(T x, Integer n, MonoidOperation op) {
   93     if(n == 0) 
   94         return 1;
   95     else {
   96         while((n & 0x1) == 0) {
   97             n >>= 1;
   98             x = op(x, x);
   99         }
  100         T result = x;
  101         n >>= 1;
  102         while(n != 0) {
  103             x = op(x, x);
  104             if((n & 0x1) != 0) 
  105                 result = op(result, x);
  106             n >>= 1;
  107         }
  108         return result;
  109     }
  110 }
  111 template <class T, class Integer>
  112 inline T power(T x, Integer n) {
  113     return power(x, n, std::multiplies<T>());
  114 }

基本算法

STL 标准中并没有区分基本算法和复杂算法,然而 SGI 却将常用的一些算法定义于 <stl_algobase.h>中,其他算法定义在 <stl_algo.h>


3.1 equal, fill, fill_n, iter_swap, lexicographical_compare, max,min,mismatch, swap

这一小节列出定义于 <stl_algobase.h>头文件中的所有算法, copy 与 copy_backward() 算法除外, 因为这两个函数复杂许多, 在效率方面有诸多考虑, 我们把他们安排在另外的小节。

equal: 序列相等性判断

  • 两个序列在 【first, last)区间内相等,equal 返回 true。
  • 如果序列的元素不均等,多出的元素不予考虑,如果第二序列元素少于第一序列, 则在遍历时很可能会越界访问造成错误。

因此,如果我们希望保证两个序列完全相等, 必须先判断其元素个数是否相等。

第一个版本,默认使用 equality 操作符,例如 vec1 == vec2
第二个版本,允许指定其谓词

  1 template <class InputIterator1, class InputIterator2>
  2 inline bool equal(InputIterator1 first1, InputIterator1 last1,
  3                   InputIterator2 first2) {
  4     for(; first1 != last1; ++first1, ++first2) {
  5         if(*first1 != *first2)
  6             return false;
  7     }
  8     return true;
  9 }
 10 
 11 template <class InputIterator1, class InputIterator2, class BindaryPredicate>
 12 inline bool equal(InputIterator1 first1, InputIterator1 last1,
 13                   InputIterator2 first2, BindaryPredicate bindary_pred) {
 14     for(; first1 != last1; ++first1, ++first2) {
 15         if(!bindary_pred(*first1, *first2) ) {
 16             return false;
 17         }
 18         return true;
 19     }
 20 }                                                                                                                                                                                     
 21 

fill: 序列填充value

将 【first, last) 内的元素全部改填新值

   22 template <class ForwardIterator, class T>                    
   23 void fill(ForwardIterator first, ForwardIterator last, const T &value) {
   24     for(; first != last; ++first) 
   25         *first = value;
   26 }
   27 
                                                                                                                                                                                                            

fill_n

将 【first, last)年内的前 n 个元素该填写新值,返回的迭代器指向被填写的最后一个元素的下一位置

   28 template <class OutputIterator, class Size, class T>29 OutputIterator fill_n(OutputIterator first, Size n, const T &value) {
   30     for(; n > 0;  --n, ++first) 
   31         *first = value;
   32     return first;
   33 }
   34 
   35        

如果 n 超越了容器的现有大小, 则会造成不可预知的后果

iterator_swap: 迭代器的交换

将两个 ForwardIterators 所指的对象对调。

 36 template <class ForwardIterator1, class ForwardIterator2>
 37 inline void iter_swap(ForwardIterator1 a, ForwardIterator2 b) { 
 38     using value_type = typename std::iterator_traits<ForwardIterator1>::value_type;
 39     value_type tmp_val = *a;
 40     *a = *b;
 41     *b = tmp_val;
 42 }

lexicographical_compare: 判断两个序列的字典序大小

以“字典排列方式” 对两个序列【first1, last1) 和 【first2,last2)进行比较, 比较操作针对两序列中的对应位置上的元素进行,并持续直到

(1)某一组对应元素彼此不相等;
(2)同时到达 last1 和 last2 (当两序列的大小相同);
(3) 到达 last1 或 last2(当两序列的大小不同)

当这个函数在对应位置上发现第一组不相等的元素时, 有下列几种可能:

  • 如果第一序列的元素较小, 返回true, 否则返回 false
  • 如果到达 last1而尚未达到 last2,返回 true
  • 如果到达 last 2 而尚未达到 last, 返回 false
  • 如果同时到达 last1 和 last2 (换句话说所有元素都匹配), 返回 false;第一序列以字典排列方式而言不小于第二序列。
  1. 第一版本以小于号进行比较
  2. 第二版本以自定义比较谓词进行比较
   44 template <class InputIterator1, class InputIterator2>
   45 bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1,
   46                              InputIterator2 first2, InputIterator2 last2) {
   47     //若一方到达尾端就结束,否则就一一对比
   48     for(; first1 != last1 && first2 != last2; ++first1, ++first2) {
   49         if(*first1 < *first2)
   50             return true;
   51         if(*first2 < *first1)
   52             return false;
   53     }
   54 
   55     return first1 == last1 && first2 != last2;
   56 }
   57 template <class InputIterator1, class InputIterator2, class Compare>
   58 bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1,59                              InputIterator2 first2, InputIterator2 last2, Compare comp) {
   60     for(; first1 != last1 && first2 != last2; ++first1, ++first2) {
   61         if(comp(*first1, *first2))
   62             return true;
   63         if(comp(*first1, *first2))
   64             return false;
   65     }
   66 
   67     return first1 == last1 && first2 != last2;
   68 }
   69 
   70   

为了增进效率, SGI 设计了一个特例化版本, 用于原生指针 const unsigned char *;
采用的是 memcmp 原生的C标准库函数,比较其每一个字节

inline bool lexicographical_compare(
	const unsigned char *first1,
	const unsigned char *last1,
	const unsigned char *first2,
	const unsigned char *last2
	)
{
  const size_t len1 = last1 - first1;
  const size_t len2 = last2 - first2;
  const int result = memcmp(first1, first2, std::min(len1, len2));
  return result != 0 ? result < 0 : len1 < len2;
}

max:取最大值

取两个对象中的最大值,一个版本使用 greate-than 操作符判断大小,一个使用 仿函数 compare 来判断大小;

template <class T>
inline const T& max(const T &a, const T &b) {
  return a < b ? b : a;
}


template <class T, class Compare>
inline const T &max(const T &a, const T &b, Compare comp) {
  return comp(a,b) ? b : a;
}

min:取最小值

取两个对象中的最小值,一个版本使用 less-than 操作符判断大小,一个使用 仿函数 compare 来判断大小;

template <class T>
inline const T& min(const T &a, const T &b) {
  return a < b ? a : b;
}


template <class T, class Compare>
inline const T &min(const T &a, const T &b, Compare comp) {
  return comp(a,b) ? a : b;
}

mismatch: 找出不匹配点

用于平行比较两个序列, 指出两者之间的第一个不匹配点,返回一对迭代器,分别指向两序列中的不匹配点。

  • 如果两个序列所有对应元素都匹配,返回则是两序列各自的last迭代器
  • 缺省情况下是用 equality 操作符来比较元素,第二版本允许用户指定其比较操作
  • 如果第二序列比第一个序列元素多,多出元素忽略不计,如果第二序列的元素个数比第一序列少,会发生未可预期的行为。
template <class InputIterator1, class InputIterator2>
pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, InputIterator last1, 
                                              InputIterator1 first2) {
    while(first1 != last1 && *first1 == *first2) {
        ++first1;
        ++first2;
     }
     return pair<InputIterator1, InputIterator2>(first1, first2);
}

template <class InputIterator1, class InputIterator2, class BinaryPredicate>
pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, InputIterator last1, 
                                              InputIterator1 first2, BinaryPredicate binary_pred) {
    while(first1 != last1 && binary_pred(*first1, *first2)) {
        ++first1;
        ++first2;
     }
     return pair<InputIterator1, InputIterator2>(first1, first2);
}



swap:交互

交互两个对象的内容

template <class T>
inline void swap(T &a, T &b) {
  T tmp = a;
  a = b;
  b = tmp;
}

3.2 copy --强化效率无所不用其极

不同的传参决定不同的 copy 版本

正常版本的使用

传入迭代器

*(result) = *first
*(result + 1) = *(first + 1) //向前推进

特例化的版本

传入字符指针,const char *

使用 memmove()

COPY的区间重叠问题

  • 当 result 的终点 result + (last-first) 在 区间 [first , last) 中,则无影响。
  • 当result 在 区间 [first, last) 中,则会可能出错

如果迭代器为原生指针(RandomIterator)的话,不会出错,因为使用的是 memmove 操作,memmove是会预报留输入区间,因此没有覆盖的危险。

copy(first,last, result);

返回值为拷贝的末尾

3.3 copy_backward 反向拷贝

倒叙拷贝

3.4 set 相关算法

set_union: 构建两个集合并集

set_union 可构建 S1,S2的并集, 此集合内含 S1 或 S2 内的每一个元素。

  • S1, S2 及其并集都是以排序区间表示
  • 返回为一个迭代器,指向输出区间的尾部

若一个元素在 S1 出现 n 次, S2 出现 m 次,那么该值在输出区间内会出现 max(m,n )次,其中 n个来自 s1,其余来自 s2

其他特点: 稳定排序,第一版本是 operator< 比较,第二版本使用仿函数 comp 进行比较

template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_union(InputIterator1 first1, InputIterator1 last1,
						 InputIterator2 first2, InputIterator2 last2,
						 OutputIterator result) {
  while (first1 != last1 && first2 != last2) {
    if(*first1 < *first2) {
      *result = *first1;
      ++first1;
    } else if(*first2 < *first1) {
      *result = *first2;
      ++first2;
    } else {
      *result = *first1;
      ++first1;
      ++first2;
    }
    ++result;
  }
  return std::copy(first2, last2, std::copy(first1, last1, result));
}

set_intersection: 构建两个集合交集

算法set_intersection可构建 s1, s2交集, 此集合内含同时出现于 s1 和 s2 内的每一个元素。

  • s1,s2 及其交集以排序区间表示
  • 返回一个迭代器,指向输出区间的尾端。
  • 如果一个元素在两个区间内各有 m,n 则最终输出区间中会出现 min(m, n) 次
  • 稳定的(stable) ,且第一版本使用 operator< 比较,第二版本采用仿函数 comp 进行比较
template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1,
								InputIterator2 first2, InputIterator2 last2,
								OutputIterator result) {
  while(first1 != last1 && first2 != last2) {
    if(*first1 < *first2) {
      ++first1;
    } else if(*first2 < *first1) 
      ++first2;
    else {
      *result = *first1;
      ++first1;
      ++first2;
      ++result;
    }
  }
  return result;
}

set_difference:构建两个集合差集

算法set_difference 可构造 s1, s2 差集, s1-s2 “出现于s1 但不出现于 s2 ”的每一个元素。

  • s1, s2 及其交集都是以排序区间表示
  • 返回值为一个迭代器,指向输出区间的尾部
  • 如果一个元素在 s1出现 m 次, s2 出现 n 次,那么该值在输出区间出现 max((m-n), 0) 次
  • 稳定操作,第一版本使用 operator< 比较, 第二版本使用 仿函数 comp 比较
template <class  InputIteraotr1, class InputIteraotr2, class OutputIterator>
OutputIterator set_difference(InputIteraotr1 first1, InputIteraotr1 last1,
							  InputIteraotr2 first2, InputIteraotr2 last2,
							  OutputIterator result) {
  //当两个区间都未达到尾端时,执行如下操作
  while(first1 != last1 && first2 != last2) {
    if(*first1 < *first2) {
      *result = *first1;
      ++result;
    } else if(*first2 < *first1) {
      ++first2;
    } else {
      ++first1;
      ++first2;
    }
  }
  return std::copy(first1, last1, result);
}

set_symmetric_difference:构建两个集合对称差集

求 S1, S2 的对称差集 ( S1-S2)U (S2-S1)

包含:出现在 S1但不出现 S2 以及 出现 S2 但不出现在S1的每一个元素

  • s1,s2 都为排序区间
  • 返回值为一个迭代器,指向输出区间的尾端
  • 当 s1 和 s2 内的每个元素都不需唯一, 因此当某个值在 s1中出现n次,在 s2 出现 m 次,那么该值在输出区间会出现 |n-m|次。
  • 稳定操作,第一版本使用 operator< 进行比较, 第二版本采用仿函数 comp
template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_syymmetric_difference(InputIterator1 first1,
										 InputIterator1 last1,
										 InputIterator2 first2,
										 InputIterator2 last2,
										 OutputIterator result) {
  while(first1 != last1 && first2 != last2) {
    if(*first1 < *first2) {
      *result = *first1;
      ++first1;
      ++result;
    } else if(*first2 < *first1) {
      ++result = *first2;
      ++first2;
      ++result;
    } else {
      ++first1;
      ++first2;
    }
  }
  return std::copy(first2, last2, std::copy(first1,last1, result));
}

3.4 heap 算法

  vector<int> ivec;
  make_heap(ivec.begin(), ivec.end(), greater<int>());
  ivec.push_back(1);
  push_heap(ivec.begin(), ivec.end(), greater<int>());
  pop_heap(ivec.begin(), ivec.end());
  ivec.pop_back();
  sort_heap(ivec.begin(), ivec.end(), greater<int>());

3.5 单纯的数据处理算法

adjacent_find : 找出满足条件的相邻元素

默认找两元素相等, 另外一个版本可以通过写出二元运算来执行算法

  • 返回相邻元素相等的起点的迭代器,未找到返回 last
template <class ForwardIterator>
ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last) {
  if(first == last)
    return last;
  ForwardIterator next = first;
  while(++next != last) {
    if(*first == *next)
      return first;
    first = next;
  }
  return last;
}
template <class ForwardIterator, class BinaryPredicate>
ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last,
							  BinaryPredicate binary_predicate) {
  if(first == last)
    return last;
  ForwardIterator next = first;
  while(++next != last) {
    if(binary_predicate(*first, *next))
      return first;
    first = next;
  }
  return last;
}

count 与 count_if : 统计指定元素的个数

  • 运用 operator= 操作符,将区间【first, last) 区间内的每一个元素拿来和指定值 value 比较,返回与 value相等的元素个数。
template <class InputIterator, class T>
typename iterator_traits<InputIterator>::difference_type
count(InputIterator first, InputIterator last, const T &value) {
  typename iterator_traits<InputIterator>::difference_type n = 0;
  for(; first != last; ++first) {
    if(*first == value)
      ++n;
  }
  return n;
}
template <class InputIterator, class Predicate>
typename iterator_traits<InputIterator>::difference_type
count_if(InputIterator first, InputIterator last, Predicate pred) {
  typename iterator_traits<InputIterator>::difference_type n = 0;
  for(; first != last; ++first) {
	if(pred(*first))
	  ++n;
  }
  return n;
}

find 和 find_if :查找第一个满足条件的元素

  • 默认采用 operator= 来循序查找区间内符合等同的元素, find_if 提供了仿函数,令仿函数运算结果为 true的元素即符合条件
  • 返回为找到的元素的迭代器, 否则返回 迭代器 last
template <class InputIterator, class T>
InputIterator find(InputIterator first, InputIterator last,
				   const T &value) {
  while(first != last && *first != value)
    ++first;
  return first;
}
template <class InputIterator, class Predicate>
InputIterator find_if(InputIterator first, InputIterator last,
					  Predicate pred) {
  while(first != last && !(pred(*first)))
    ++first;
  return first;
}

find_end: 在序列1中查找序列2的最后一次出现点

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

for_each : 遍历每一个元素,将仿函数 f 施加其每一个元素

  • 只读算法, 迭代器为 inputiterator, 如果修改应该使用 transform
template <class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f) {
  for(; first != last; ++first)
   f(*first);
  return f;
}

includes: s2 是否被包含于 s1 中

  • s1 s2 均为有序区间
  • include 算法可供用户选择 less 或 greater 进行两元素的大小比较
    使用:
includes(s1.begin(), s1.end(), s2.begin(), s2.end());
includes(s1.begin(), s1.end(), s2.begin(), s2.end(), greater<int>());
template <class InputIterator1, class InputIterator2>
bool includes(InputIterator1 first1, InputIterator1 last1,
			  InputIterator2 first2, InputIterator2 last2) {
  while(first1 != last1 && first2 != last2) {
    if(*first2 < *first1)
      return false;
    else if(*first1 < *first2)
      ++first1;
    else
      ++first1, ++first2;
  }
  return first2 == last2;
}

max_element/min_element: 求序列中的最大/小元素


template <class ForwardIterator>
ForwardIterator max_element(ForwardIterator first, ForwardIterator last) {
  if(first == last)
    return first;
  ForwardIterator result = first;
  while(++first != last)
    if(*result < *first)
      result = first;
    
  return result;
}
template <class ForwardIterator, class Compare>
ForwardIterator max_element(ForwardIterator first, ForwardIterator last,
							Compare comp) {
  if(first == last)
	return first;
  ForwardIterator result = first;
  while(++first != last)
	if(comp(*result, *first))
	  result = first;

  return result;
}

merge 合并两个有序区间

  • 排序后的 S1 和 S2
  • 返回为合并后的序列的末尾
template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator merge(InputIterator1 first1, InputIterator1 last1,
					 InputIterator2 first2, InputIterator2 last2,
					 OutputIterator result) {
  while(first1 != last1 && first2 != last2) {
    if(*first2 < *first1) {
      *result = *first2;
      ++first2;
    }
    else {
      *result = *first1;
      ++first1;
    }
    ++result;
  }
  return std::copy(first2, last2, std::copy(first1, last1, result));
}

partition :分割排列元素,将满足特定条件的元素放在区间前半段

  • 对于 仿函数判定为 true 的元素放于区间的前段, 判定为 false 的元素放于区间的后半段。
  • 非稳定性分割,如果需要稳定使用 stable_partition
template <class BidirectionalIterator, class Predicate>
BidirectionalIterator partition(BidirectionalIterator first,
								BidirectionalIterator last,
								Predicate pred) {
 
  while(true) {
    while(true) 
      if(first == last)
        return first;
      else if(pred(*first))
        ++first;
      else 
        break;
      
    --last;
    while(true)
      if(first == last)
        return first;
      else if(!pred(*last))
        --last;
      else 
        break;
    iter_swap(first, last);
    ++first;
  }
}

remove 移除元素(但不是删除)

  • 移除区间内所有与 value 相等的元素, 并不是真正从容器中删除那些元素, 而是将每一个不与 value 相等的元素轮番赋值给 first 之后的空间。
  • 对于array,更喜欢的是 remove_copy 和 remove_copy_if 版本
  • 返回删除后的数组的末尾元素的下一个位置。
template <class InputIterator, class OutputIterator, class T>
OutputIterator remove_copy(InputIterator first, InputIterator last,
						   OutputIterator result, const T &value) {
  for(; first != last; ++first) {
    if(*first != value) {
      *result = *first;
      ++result;
    }
  }
  return result;
}
template <class InputIterator, class OutputIterator, class Predicate>
OutputIterator remove_copy_if(InputIterator first, InputIterator last,
						   OutputIterator result, Predicate pred) {
  for(; first != last; ++first) {
	if(!pred(*first)) {
	  *result = *first;
	  ++result;
	}
  }
  return result;
}
template <class ForwardIterator, class T>
ForwardIterator remove(ForwardIterator first, ForwardIterator last,
					   const T &value) {
  first = find(first, last, value);
  ForwardIterator next = first;
  return first == last ? first : remove_copy(++next, last, first, value);
}

template <class ForwardIterator, class Predicate>
ForwardIterator remove_if(ForwardIterator first, ForwardIterator last,
						  Predicate pred) {
  first = find_if(first, last, pred);
  ForwardIterator next = first;
  return first == last ? first : remove_copy_if(++next, last, first, pred);
}

replace : 将区间内的所有 old_value 全部用 new_value 取代

template <class ForWardIterator, class T>
void replace(ForWardIterator first, ForWardIterator last,
			 const T &old_val, const T &new_val) {
  for(; first != last; ++first)
    if(*first == old_val)
      *first = new_val;
}

template <class ForWardIterator, class OutputIterator, class T>
void replace_copy(ForWardIterator first, ForWardIterator last,
			      OutputIterator result,
			      const T &old_val, const T &new_val) {
  for(; first != last; ++first)
	if(*first == old_val)
	  *first = new_val;
}

template <class ForwardIterator, class Predicate, class T>
void replace_if(ForwardIterator first, ForwardIterator last,
				Predicate pred, const T &new_val) {
  for(; first != last; ++first)
    if(pred(*first))
      *first = new_val;
}

template <class Iterator, class OutputIterator, class Predicate, class T>
OutputIterator replace_copy_if(Iterator first, Iterator last,
							   OutputIterator result, Predicate pred,
							   const T &new_value) {
  for(; first != last; ++first, ++result) {
    *result = pred(*first) ? new_value : *first;
  }
  return result;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值