STL源码剖析——数值算法stl_numeric.h

太过爱你忘了你带给我的痛 2022-08-12 16:20 269阅读 0赞

前言

在STL中,算法是独立于特定的数据结构,称为泛型算法。本节介绍的数值算法是在源码SGI STL中的文件,具体功能详见下面的源码剖析,在源码剖析的时候,针对每个元素都给出了使用例子,这样可以增加对其理解。

numeric数值算法源码剖析

  1. #ifndef __SGI_STL_INTERNAL_NUMERIC_H
  2. #define __SGI_STL_INTERNAL_NUMERIC_H
  3. __STL_BEGIN_NAMESPACE
  4. /*
  5. sum (1) :The default operation is to add the elements up;
  6. 这个版本的默认操作时累加;
  7. template <class InputIterator, class T>
  8. T accumulate (InputIterator first, InputIterator last, T init);
  9. custom (2): a different operation can be specified as binary_op;
  10. 这个版本的操作可以是用户通过binary_op自行指定;指定函数在<stl_function.h>定义,也可自己定义
  11. template <class InputIterator, class T, class BinaryOperation>
  12. T accumulate (InputIterator first, InputIterator last, T init,
  13. BinaryOperation binary_op);
  14. */
  15. //第一个版本:默认操作是累加
  16. //计算[first,last)区间元素与init的和
  17. //返回一个副本
  18. template <class _InputIterator, class _Tp>
  19. _Tp accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
  20. {
  21. __STL_REQUIRES(_InputIterator, _InputIterator);
  22. for ( ; __first != __last; ++__first)//遍历指定范围元素
  23. __init = __init + *__first;//将每个元素累加到初始值init上
  24. return __init;
  25. }
  26. //第二个版本:用户可自行指定二元操作函数
  27. template <class _InputIterator, class _Tp, class _BinaryOperation>
  28. _Tp accumulate(_InputIterator __first, _InputIterator __last, _Tp __init,
  29. _BinaryOperation __binary_op)
  30. {
  31. __STL_REQUIRES(_InputIterator, _InputIterator);
  32. for ( ; __first != __last; ++__first)//遍历指定范围元素
  33. __init = __binary_op(__init, *__first);//对每个元素执行二元操作
  34. return __init;
  35. }
  36. //下面举例子:
  37. /*accumulate example:
  38. #include <iostream> // std::cout
  39. #include <functional> // std::minus
  40. #include <numeric> // std::accumulate
  41. int myfunction (int x, int y) {return x+2*y;}
  42. struct myclass {
  43. int operator()(int x, int y) {return x+3*y;}
  44. } myobject;
  45. int main () {
  46. int init = 100;
  47. int numbers[] = {10,20,30};
  48. std::cout << "using default accumulate: ";
  49. std::cout << std::accumulate(numbers,numbers+3,init);
  50. std::cout << '\n';
  51. std::cout << "using functional's minus: ";
  52. std::cout << std::accumulate (numbers, numbers+3, init, std::minus<int>());
  53. std::cout << '\n';
  54. std::cout << "using custom function: ";
  55. std::cout << std::accumulate (numbers, numbers+3, init, myfunction);
  56. std::cout << '\n';
  57. std::cout << "using custom object: ";
  58. std::cout << std::accumulate (numbers, numbers+3, init, myobject);
  59. std::cout << '\n';
  60. return 0;
  61. }
  62. Output:
  63. using default accumulate: 160
  64. using functional's minus: 40
  65. using custom function: 220
  66. using custom object: 280
  67. */
  68. /*默认操作是把内积(相乘)的值与初始值init相加
  69. 用户可以自行指定操作类型
  70. sum/multiply (1)
  71. template <class InputIterator1, class InputIterator2, class T>
  72. T inner_product (InputIterator1 first1, InputIterator1 last1,
  73. InputIterator2 first2, T init);
  74. custom (2)
  75. template <class InputIterator1, class InputIterator2, class T,
  76. class BinaryOperation1, class BinaryOperation2>
  77. T inner_product (InputIterator1 first1, InputIterator1 last1,
  78. InputIterator2 first2, T init,
  79. BinaryOperation1 binary_op1,
  80. BinaryOperation2 binary_op2);
  81. */
  82. //描述:The two default operations (to add up the result of multiplying the pairs)
  83. //may be overridden by the arguments binary_op1 and binary_op2.
  84. //功能:Returns the result of accumulating init with the inner products of the pairs
  85. //formed by the elements of two ranges starting at first1 and first2.
  86. //版本一:使用默认操作
  87. template <class _InputIterator1, class _InputIterator2, class _Tp>
  88. _Tp inner_product(_InputIterator1 __first1, _InputIterator1 __last1,
  89. _InputIterator2 __first2, _Tp __init)
  90. {
  91. __STL_REQUIRES(_InputIterator2, _InputIterator);
  92. __STL_REQUIRES(_InputIterator2, _InputIterator);
  93. //以第一个序列的元素个数为据,将两个序列都走一遍
  94. for ( ; __first1 != __last1; ++__first1, ++__first2)、
  95. __init = __init + (*__first1 * *__first2);//执行两个序列的内积与初始值init相加
  96. return __init;
  97. }
  98. //版本二:用户可自行指定二元操作函数
  99. template <class _InputIterator1, class _InputIterator2, class _Tp,
  100. class _BinaryOperation1, class _BinaryOperation2>
  101. _Tp inner_product(_InputIterator1 __first1, _InputIterator1 __last1,
  102. _InputIterator2 __first2, _Tp __init,
  103. _BinaryOperation1 __binary_op1,
  104. _BinaryOperation2 __binary_op2)
  105. {
  106. __STL_REQUIRES(_InputIterator2, _InputIterator);
  107. __STL_REQUIRES(_InputIterator2, _InputIterator);
  108. //以第一个序列的元素个数为据,将两个序列都走一遍
  109. for ( ; __first1 != __last1; ++__first1, ++__first2)
  110. //首先指定__binary_op2操作,再指定__binary_op1操作
  111. __init = __binary_op1(__init, __binary_op2(*__first1, *__first2));
  112. return __init;
  113. }
  114. //下面举例子:
  115. /*inner_product example:
  116. #include <iostream> // std::cout
  117. #include <functional> // std::minus, std::divides
  118. #include <numeric> // std::inner_product
  119. int myaccumulator (int x, int y) {return x-y;}
  120. int myproduct (int x, int y) {return x+y;}
  121. int main () {
  122. int init = 10;
  123. int series1[] = {10,20,30};
  124. int series2[] = {1,2,3};
  125. std::cout << "using default inner_product: ";
  126. std::cout << std::inner_product(series1,series1+3,series2,init);
  127. std::cout << '\n';
  128. std::cout << "using functional operations: ";
  129. std::cout << std::inner_product(series1,series1+3,series2,init,
  130. std::minus<int>(),std::divides<int>());
  131. std::cout << '\n';
  132. std::cout << "using custom functions: ";
  133. std::cout << std::inner_product(series1,series1+3,series2,init,
  134. myaccumulator,myproduct);
  135. std::cout << '\n';
  136. return 0;
  137. }
  138. Output:
  139. using default inner_product: 150
  140. using functional operations: -20
  141. using custom functions: -56
  142. */
  143. //局部求和
  144. /*功能与描述:
  145. Assigns to every element in the range starting at result the partial sum of
  146. the corresponding elements in the range [first,last).
  147. If x represents an element in [first,last) and y represents an element in result, the ys can be calculated as:
  148. y0 = x0
  149. y1 = x0 + x1
  150. y2 = x0 + x1 + x2
  151. y3 = x0 + x1 + x2 + x3
  152. y4 = x0 + x1 + x2 + x3 + x4
  153. ... ... ...
  154. */
  155. /*版本一:默认操作是:The default operation is to add the elements up;
  156. sum (1)
  157. template <class InputIterator, class OutputIterator>
  158. OutputIterator partial_sum (InputIterator first, InputIterator last,
  159. OutputIterator result);
  160. 版本二:用户可以自行指定二元操作:operation can be specified as binary_op instead.
  161. custom (2)
  162. template <class InputIterator, class OutputIterator, class BinaryOperation>
  163. OutputIterator partial_sum (InputIterator first, InputIterator last,
  164. OutputIterator result, BinaryOperation binary_op);
  165. */
  166. //版本一:默认操作函数
  167. template <class _InputIterator, class _OutputIterator, class _Tp>
  168. _OutputIterator
  169. __partial_sum(_InputIterator __first, _InputIterator __last,
  170. _OutputIterator __result, _Tp*)
  171. {
  172. _Tp __value = *__first;
  173. while (++__first != __last) {//遍历区间元素
  174. __value = __value + *__first;//区间前n个元素的总和
  175. *++__result = __value;//把元素赋给输出端
  176. }
  177. return ++__result;
  178. }
  179. template <class _InputIterator, class _OutputIterator>
  180. _OutputIterator
  181. partial_sum(_InputIterator __first, _InputIterator __last,
  182. _OutputIterator __result)
  183. {
  184. __STL_REQUIRES(_InputIterator, _InputIterator);
  185. __STL_REQUIRES(_OutputIterator, _OutputIterator);
  186. if (__first == __last) return __result;//若为空
  187. *__result = *__first;//初始值
  188. //调用上面的函数,萃取出first的类型方便上面函数使用
  189. return __partial_sum(__first, __last, __result, __VALUE_TYPE(__first));
  190. }
  191. //版本二:用户指定二元操作函数
  192. template <class _InputIterator, class _OutputIterator, class _Tp,
  193. class _BinaryOperation>
  194. _OutputIterator
  195. __partial_sum(_InputIterator __first, _InputIterator __last,
  196. _OutputIterator __result, _Tp*, _BinaryOperation __binary_op)
  197. {
  198. _Tp __value = *__first;
  199. while (++__first != __last) {//遍历区间元素
  200. __value = __binary_op(__value, *__first);//区间前n个元素的__binary_op
  201. *++__result = __value;//把元素赋给输出端
  202. }
  203. return ++__result;
  204. }
  205. template <class _InputIterator, class _OutputIterator, class _BinaryOperation>
  206. _OutputIterator
  207. partial_sum(_InputIterator __first, _InputIterator __last,
  208. _OutputIterator __result, _BinaryOperation __binary_op)
  209. {
  210. __STL_REQUIRES(_InputIterator, _InputIterator);
  211. __STL_REQUIRES(_OutputIterator, _OutputIterator);
  212. if (__first == __last) return __result;
  213. *__result = *__first;
  214. //调用上面的函数,萃取出first的类型方便上面函数使用
  215. return __partial_sum(__first, __last, __result, __VALUE_TYPE(__first),
  216. __binary_op);
  217. }
  218. //下面举例:
  219. /*partial_sum example:
  220. #include <iostream> // std::cout
  221. #include <functional> // std::multiplies
  222. #include <numeric> // std::partial_sum
  223. int myop (int x, int y) {return x+y+1;}
  224. int main () {
  225. int val[] = {1,2,3,4,5};
  226. int result[5];
  227. std::partial_sum (val, val+5, result);
  228. std::cout << "using default partial_sum: ";
  229. for (int i=0; i<5; i++) std::cout << result[i] << ' ';
  230. std::cout << '\n';
  231. std::partial_sum (val, val+5, result, std::multiplies<int>());
  232. std::cout << "using functional operation multiplies: ";
  233. for (int i=0; i<5; i++) std::cout << result[i] << ' ';
  234. std::cout << '\n';
  235. std::partial_sum (val, val+5, result, myop);
  236. std::cout << "using custom function: ";
  237. for (int i=0; i<5; i++) std::cout << result[i] << ' ';
  238. std::cout << '\n';
  239. return 0;
  240. }
  241. Output:
  242. using default partial_sum: 1 3 6 10 15
  243. using functional operation multiplies: 1 2 6 24 120
  244. using custom function: 1 4 8 13 19
  245. */
  246. /*功能与描述:
  247. Assigns to every element in the range starting at result the difference
  248. between its corresponding element in the range [first,last)
  249. and the one preceding it (except for *result, which is assigned *first).
  250. If x represents an element in [first,last) and y represents an element in result, the ys can be calculated as:
  251. y0 = x0
  252. y1 = x1 - x0
  253. y2 = x2 - x1
  254. y3 = x3 - x2
  255. y4 = x4 - x3
  256. ... ... ...
  257. The default operation is to calculate the difference, but some other operation can be specified as binary_op instead.
  258. */
  259. /*
  260. difference (1)
  261. template <class InputIterator, class OutputIterator>
  262. OutputIterator adjacent_difference (InputIterator first, InputIterator last,
  263. OutputIterator result);
  264. custom (2)
  265. template <class InputIterator, class OutputIterator, class BinaryOperation>
  266. OutputIterator adjacent_difference ( InputIterator first, InputIterator last,
  267. OutputIterator result, BinaryOperation binary_op );
  268. */
  269. //版本一:默认操作函数
  270. template <class _InputIterator, class _OutputIterator, class _Tp>
  271. _OutputIterator
  272. __adjacent_difference(_InputIterator __first, _InputIterator __last,
  273. _OutputIterator __result, _Tp*)
  274. {
  275. _Tp __value = *__first;
  276. while (++__first != __last) {//遍历区间
  277. _Tp __tmp = *__first;//初始化tmp
  278. *++__result = __tmp - __value;//计算相邻两元素的差额(后-前),并赋给输出端
  279. __value = __tmp;//更新当前值
  280. }
  281. return ++__result;
  282. }
  283. template <class _InputIterator, class _OutputIterator>
  284. _OutputIterator
  285. adjacent_difference(_InputIterator __first,
  286. _InputIterator __last, _OutputIterator __result)
  287. {
  288. __STL_REQUIRES(_InputIterator, _InputIterator);
  289. __STL_REQUIRES(_OutputIterator, _OutputIterator);
  290. if (__first == __last) return __result;//若为空直接返回
  291. *__result = *__first;//初始值
  292. //调用上面的函数__adjacent_difference()
  293. return __adjacent_difference(__first, __last, __result,
  294. __VALUE_TYPE(__first));
  295. }
  296. //版本二:可指定操作函数
  297. template <class _InputIterator, class _OutputIterator, class _Tp,
  298. class _BinaryOperation>
  299. _OutputIterator
  300. __adjacent_difference(_InputIterator __first, _InputIterator __last,
  301. _OutputIterator __result, _Tp*,
  302. _BinaryOperation __binary_op) {
  303. _Tp __value = *__first;
  304. while (++__first != __last) {//遍历区间
  305. _Tp __tmp = *__first;//初始化tmp
  306. *++__result = __binary_op(__tmp, __value);//计算相邻两元素的操作,并赋给输出端
  307. __value = __tmp;//更新当前值
  308. }
  309. return ++__result;
  310. }
  311. template <class _InputIterator, class _OutputIterator, class _BinaryOperation>
  312. _OutputIterator
  313. adjacent_difference(_InputIterator __first, _InputIterator __last,
  314. _OutputIterator __result, _BinaryOperation __binary_op)
  315. {
  316. __STL_REQUIRES(_InputIterator, _InputIterator);
  317. __STL_REQUIRES(_OutputIterator, _OutputIterator);
  318. if (__first == __last) return __result;//若为空直接返回
  319. *__result = *__first;//初始值
  320. //调用上面的函数__adjacent_difference()
  321. return __adjacent_difference(__first, __last, __result,
  322. __VALUE_TYPE(__first),
  323. __binary_op);
  324. }
  325. //下面举例子:
  326. /*adjacent_difference example:
  327. #include <iostream> // std::cout
  328. #include <functional> // std::multiplies
  329. #include <numeric> // std::adjacent_difference
  330. int myop (int x, int y) {return x+y;}
  331. int main () {
  332. int val[] = {1,2,3,5,9,11,12};
  333. int result[7];
  334. std::adjacent_difference (val, val+7, result);
  335. std::cout << "using default adjacent_difference: ";
  336. for (int i=0; i<7; i++) std::cout << result[i] << ' ';
  337. std::cout << '\n';
  338. std::adjacent_difference (val, val+7, result, std::multiplies<int>());
  339. std::cout << "using functional operation multiplies: ";
  340. for (int i=0; i<7; i++) std::cout << result[i] << ' ';
  341. std::cout << '\n';
  342. std::adjacent_difference (val, val+7, result, myop);
  343. std::cout << "using custom function: ";
  344. for (int i=0; i<7; i++) std::cout << result[i] << ' ';
  345. std::cout << '\n';
  346. return 0;
  347. }
  348. output:
  349. using default adjacent_difference: 1 1 1 2 4 2 1
  350. using functional operation multiplies: 1 2 6 15 45 99 132
  351. using custom function: 1 3 5 8 14 20 23
  352. */
  353. // Returns __x ** __n, where __n >= 0. _Note that "multiplication"
  354. // is required to be associative, but not necessarily commutative.
  355. //power为SGI专属,并不在STL标准之列,它用来计算某数的n幂次方。
  356. // 版本一,幂次方。如果指定为乘法运算,则当n >= 0 时传回 x^n。
  357. // 注意,"multiplication" 必须满足结合律(associative),
  358. // 但不需满足交换律(commutative)。
  359. template <class _Tp, class _Integer, class _MonoidOperation>
  360. _Tp __power(_Tp __x, _Integer __n, _MonoidOperation __opr)
  361. {
  362. if (__n == 0)
  363. return identity_element(__opr);
  364. else {
  365. while ((__n & 1) == 0) {
  366. __n >>= 1;
  367. __x = __opr(__x, __x);
  368. }
  369. _Tp __result = __x;
  370. __n >>= 1;
  371. while (__n != 0) {
  372. __x = __opr(__x, __x);
  373. if ((__n & 1) != 0)
  374. __result = __opr(__result, __x);
  375. __n >>= 1;
  376. }
  377. return __result;
  378. }
  379. }
  380. //版本二:以 multiplies<_Tp>()操作调用版本一
  381. template <class _Tp, class _Integer>
  382. inline _Tp __power(_Tp __x, _Integer __n)
  383. {
  384. return __power(__x, __n, multiplies<_Tp>());
  385. }
  386. // Alias for the internal name __power. Note that power is an extension,
  387. // not part of the C++ standard.
  388. //对上面函数的封装
  389. template <class _Tp, class _Integer, class _MonoidOperation>
  390. inline _Tp power(_Tp __x, _Integer __n, _MonoidOperation __opr)
  391. {
  392. return __power(__x, __n, __opr);
  393. }
  394. template <class _Tp, class _Integer>
  395. inline _Tp power(_Tp __x, _Integer __n)
  396. {
  397. return __power(__x, __n);
  398. }
  399. // iota is not part of the C++ standard. It is an extension.
  400. //C++11已经把这个列为STL的标准
  401. //设定某个区间的内容,使其每个元素从指定值value开始,呈现递增
  402. //在 [first,last) 范围内內填入value, value+1, value+2...
  403. template <class _ForwardIter, class _Tp>
  404. void
  405. iota(_ForwardIter __first, _ForwardIter __last, _Tp __value)
  406. {
  407. __STL_REQUIRES(_ForwardIter, _Mutable_ForwardIterator);
  408. __STL_CONVERTIBLE(_Tp, typename iterator_traits<_ForwardIter>::value_type);
  409. while (__first != __last)
  410. *__first++ = __value++;
  411. }
  412. //举例子:
  413. /*iota example
  414. #include <iostream> // std::cout
  415. #include <numeric> // std::iota
  416. int main () {
  417. int numbers[10];
  418. std::iota (numbers,numbers+10,100);
  419. std::cout << "numbers:";
  420. for (int& i:numbers) std::cout << ' ' << i;
  421. std::cout << '\n';
  422. return 0;
  423. }
  424. output:
  425. numbers: 100 101 102 103 104 105 106 107 108 109
  426. */
  427. __STL_END_NAMESPACE
  428. #endif /* __SGI_STL_INTERNAL_NUMERIC_H */
  429. // Local Variables:
  430. // mode:C++
  431. // End:

参考资料:

《STL源码剖析》侯捷

发表评论

表情:
评论列表 (有 0 条评论,269人围观)

还没有评论,来说两句吧...

相关阅读

    相关 STL剖析】Sort算法

    前言:sort算法必须拿出来单独将,因为它是STL所有算法中最复杂最庞大的一个,就像我肯定会把copy算法单独列出来一样,这两个算法太重要了。 提示:STL算法特点是,前两个