SGISTL源码探究-stl_numeric.h中的数值算法
来源:互联网 发布:java file.getlength 编辑:程序博客网 时间:2024/06/05 04:45
前言
上一小节中,我们对stl
中的算法部分做了一个大致的说明。本小节我们将进入到其中关于数值算法的部分,都在stl_numeric.h
文件中。废话不多说,直接看源码吧。
stl_numeric
accumulate
注意该算法要求了迭代器的类型至少是InputIterator
类型,如果是OutputIterator
类型,肯定是不行的。
用于计算元素总和,init加上[first, last)范围内的元素之和。
template <class InputIterator, class T>T accumulate(InputIterator first, InputIterator last, T init) { /* 将[first, last)的值累加到init上 * 最后返回结果 */ for ( ; first != last; ++first) init = init + *first; return init;}//这里多提供了一个BinaryOperation参数。之前是执行的求和运算,现在换成binary_op,对每个元素执行binary_op操作,换成减法、乘法都可以,但是并不建议换成违背函数本意的操作。template <class InputIterator, class T, class BinaryOperation>T accumulate(InputIterator first, InputIterator last, T init, BinaryOperation binary_op) { for ( ; first != last; ++first) init = binary_op(init, *first); return init;}
inner_product
该函数用于计算[first1, last1)和[first2, first2 + (last1 - first1))的点积,最后加上init的值。
template <class InputIterator1, class InputIterator2, class T>T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init) { //遍历[first1, last)以及[first2, first2 + (last1 - first1)) for ( ; first1 != last1; ++first1, ++first2) init = init + (*first1 * *first2); return init;}//该版本的inner_product不是执行init + (*fist1 ) * (*first2)操作,而是执行传入的binary_op1以及binary_op2操作template <class InputIterator1, class InputIterator2, class T, class BinaryOperation1, class BinaryOperation2>T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, BinaryOperation1 binary_op1, BinaryOperation2 binary_op2) { for ( ; first1 != last1; ++first1, ++first2) init = binary_op1(init, binary_op2(*first1, *first2)); return init;}
partial_sum
该函数用于计算局部的和。将*result
赋值为*first
,将*(result+1)
赋值为*first + *(first+1)
依次类推。
当传入的迭代器result
为first
,这就变成了一个质变算法了。
//该函数供partial_sum调用template <class InputIterator, class OutputIterator, class T>OutputIterator __partial_sum(InputIterator first, InputIterator last, OutputIterator result, T*) { //从first + 1指向的位置开始进行累加并赋值给*result T value = *first; while (++first != last) { value = value + *first; *++result = value; } //注意返回的是result + (last - first)的位置,即当前被赋值末尾元素的下一个位置 return ++result;}//partial_sum算法,版本一template <class InputIterator, class OutputIterator>OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result) { //处理特殊情况,若first等于last,直接返回 if (first == last) return result; //将*result赋值为*first *result = *first; //从first + 1开始遍历累加,并将结果返回 return __partial_sum(first, last, result, value_type(first));}//这是针对提供了BinaryOperation的partial_sum算法版本实现的template <class InputIterator, class OutputIterator, class T, class BinaryOperation>OutputIterator __partial_sum(InputIterator first, InputIterator last, OutputIterator result, T*, BinaryOperation binary_op) { //不同之处在于之前的累加操作换成了binary_op二元操作 T value = *first; while (++first != last) { value = binary_op(value, *first); *++result = value; } return ++result;}//partial_sum版本二,提供了自己的二元操作template <class InputIterator, class OutputIterator, class BinaryOperation>OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op) { if (first == last) return result; *result = *first; return __partial_sum(first, last, result, value_type(first), binary_op);}
adjacent_difference
该函数用于计算[first, last)
中相邻元素之间的差。它将*result
的值赋为*first
,然后在[first+1, last)
范围内的元素,分别计算*(first) - *(first-1)
的值,然后分别赋值给*(result + 1)
。
在不使用自己提供的binary_op
情况下,它和partial_sum
互为逆运算。比如{1, 2, 3, 4, 5}
,执行adjacent_difference
之后,结果为{1, 1, 1, 1, 1}
,然后再对{1, 1, 1, 1, 1}
执行partial_sum
,结果又恢复成了原样,为{1, 2, 3, 4, 5}
。
//该函数实现了adjacent_difference函数的主要功能,供adjacent_difference调用。和__partial_sum的实现很像,就是执行的二元操作不一样而已。template <class InputIterator, class OutputIterator, class T>OutputIterator __adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, T*) { T value = *first; while (++first != last) { T tmp = *first; *++result = tmp - value; value = tmp; } return ++result;}//adjacent_difference,版本一template <class InputIterator, class OutputIterator>OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result) { if (first == last) return result; *result = *first; return __adjacent_difference(first, last, result, value_type(first));}//为提供了binary_op的adjacent_difference版本提供主要操作template <class InputIterator, class OutputIterator, class T, class BinaryOperation>OutputIterator __adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, T*, BinaryOperation binary_op) { T value = *first; while (++first != last) { T tmp = *first; *++result = binary_op(tmp, value); value = tmp; } return ++result;}//adjacent_difference,版本二template <class InputIterator, class OutputIterator, class BinaryOperation>OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op) { if (first == last) return result; *result = *first; return __adjacent_difference(first, last, result, value_type(first), binary_op);}
power
该函数是SGI
专属的算法,不在STL
的标准中。它的作用是计算x的n次方,当然也可以自己指定运算的类型,比如加法除法之类的。
// Returns x ** n, where n >= 0. Note that "multiplication"// is required to be associative, but not necessarily commutative.//指定运算类型 template <class T, class Integer, class MonoidOperation>T power(T x, Integer n, MonoidOperation op) { if (n == 0) return identity_element(op); else { //当n为偶数,不断的执行op,然后将n/2,直到n为奇数 while ((n & 1) == 0) { n >>= 1; x = op(x, x); } //对n为奇数时进行计算 T result = x; n >>= 1; while (n != 0) { x = op(x, x); if ((n & 1) != 0) result = op(result, x); n >>= 1; } return result; }}//调用上面的版本,通过multiplies<T>()表示做乘法运算template <class T, class Integer>inline T power(T x, Integer n) { return power(x, n, multiplies<T>());}
上面计算x的n次方的计算方式并不是依次相乘,而是采用的快速幂算法。区分奇偶,计算x^n的值,只需要O(logn)的复杂度,而不是O(n)。
快速幂算法的公式如下:
- a^b = (a^2)^b/2,b为偶数
- a^b = (a^2)^b/2*a,b为奇数
比如2的4次方,并没有采用(2)*(2)*(2)*(2)
这样依次相乘的算法,而是采用(2*2)*(2*2)
,这样的做法,这种只用2次运算,而依次相乘需要4次运算。
itoa
该函数由SGISTL
提供,并不在STL
标准中。
它并不是那个C语言里面实现的整数转字符串的函数。
而是在[first, last)
区间内将元素的值依次设置为value, value + 1, value + 2......
这是一个质变算法,改变了传入的迭代器范围指向的元素的值。
template <class ForwardIterator, class T>void iota(ForwardIterator first, ForwardIterator last, T value) { while (first != last) *first++ = value++;}
小结
本小节对stl_numeric.h
中的算法进行了分析,里面大部分算法都很简单,也就power
算法稍微需要理解下,如果有算法基础也很容易理解。除了注重算法本身,也要注意它是如何实现泛化的,这点同样也很重要。
- SGISTL源码探究-stl_numeric.h中的数值算法
- SGISTL源码探究-stl_algobase.h中的算法
- SGISTL源码探究-stl_algo.h中的基础算法
- SGISTL源码探究-stl_alog.h中的二分查找算法
- SGISTL源码探究-stl_algo.h中的排列算法
- SGISTL源码探究-stl_algo.h中的排序算法
- SGISTL源码探究-STL中的算法(前言)
- STL源码剖析——数值算法stl_numeric.h
- STL源码剖析 - 第6章 算法(algorithms) - 数值算法<stl_numeric.h>
- STL 源码剖析 算法 stl_numeric.h
- STL 源码剖析 算法 stl_numeric.h -- copy
- SGISTL源码探究-STL中的红黑树(上)
- SGISTL源码探究-STL中的红黑树(下)
- SGISTL源码探究-STL中的hashtable(上)
- SGISTL源码探究-STL中的hashtable(下)
- SGISTL源码探究-配接器
- STL源码剖析 [算法](一)[stl_numeric.h]
- SGISTL源码探究-内存池
- linux安装elasticsearch5.5
- document.forms[].submit()
- MATLAB匿名函数的应用6
- Gson 解析教程
- 关于Fresco的
- SGISTL源码探究-stl_numeric.h中的数值算法
- C/C++中 变量的存储位置
- Nginx 启动步骤
- 【解决】postman调试oAuth2.0第三方接口
- HttpServletRequest介绍
- 微信退款结果通知报文AES解密
- 侧拉菜单传值
- springmvc的ModelAttribute注解
- To enable just-in-time (JIT) debugging错误的解决方式