STL 简单 <stl_numeric.h> 算法的实现
2016-06-04 19:55
417 查看
1.简介
在STL中,算法可以大致分为两类:质变算法、非质变算法。质变算法会改变操作对象的值,非质变算法不会改变操作对象的值。所有的STL算法都作用在迭代器(iterator)所标识的区间上。本文介绍的数值算法包括:
1. accumulate:计算 [ first,last ) 内所有元素的总和;
2. adjacent_difference:计算 [ first,last ) 中相邻元素的差额;
3. inner_product:计算 [ first1,last1 ) 和[ first2, first2 + ( last1 – first1 ) ) 的一般内积;
4. partial_sum:计算局部总和;
5. power:计算某数的 n 次方;
这些数值算法不会改变操作对象,所以可以归类到非质变算法中,同时,各个数值算法的实现非常简单,没有包含高技巧性的代码。
2.设计与实现
我用VS2013写的程序(github),数值算法的实现版本的位于cghSTL/version/cghSTL-0.5.1.rar数组算法的实现需要以下文件:
1. cghVector.h,自己实现的vector,位于cghSTL/sequence
containers/cghVector/,想了解vector实现细节的同学请移步:STL简单vector的实现
2. cghUtil.h:算法的输出会用到pair结构体,我把pair自己实现了一遍,cghUtil.h 位于cghSTL/cghUtil/
3. cghStl_numeric.h,本文的主角:数值算法,位于cghSTL/algorithms/
4. test_algorithms_numeric.cpp,测试文件,位于cghSTL/test/
为了增强代码的可读性,我用region把各个算法隔开,如下图所示
数值算法一点不难,直接上代码吧,注释已经说明了一切~
cghStl_numeric.h
/******************************************************************* * Copyright(c) 2016 Chen Gonghao * All rights reserved. * * chengonghao@yeah.net * * 文件内容:cghSTL 数值算法 ******************************************************************/ #ifndef _CGH_STL_ALGORITHMS_NUMERIC_ #define _CGH_STL_ALGORITHMS_NUMERIC_ #include "cghUtil.h" namespace CGH{ #pragma region accumulate /* accumulate算法用来计算 init 和 [ first, last )内所有元素的总和 必须提供 init ,因为当 [ first, last )为空时仍能获得一个明确定义的值 如果希望计算 [ first, last )中所有数值的总和,应该将 init 设为 0 */ template<class iterator, class T> T accumulate(iterator first, iterator last, T init) { for (; first != last; ++first) { init = init + *first; // 将每个元素值累加到 init 上 } return init; } /* binaryOp:用户指定的计算方法 */ template<class iterator, class T, class binaryOp> T accumulate(iterator first, iterator last, T init, binaryOp binary_op) { for (; first != last; ++first) { init = binary_op(init, *first); // binary_op:特定的计算方式 } return init; } #pragma endregion #pragma region ajacent_difference /* ajacent_difference 算法用来计算[ first, last ] 中相邻元素的差额 */ template<class InputIterator, class OutputIterator> OutputIterator ajacent_difference(InputIterator first, InputIterator last, OutputIterator result) { if (first == last) { return result; } *result = *first; // 记录第一个元素 iterator_traits<InputIterator>::value_type value = *first; // 利用特性萃取机取出value_type的类型 while (++first != last) { iterator_traits<InputIterator>::value_type tmp = *first; // 将相邻两个元素的差值赋给result *++result = tmp - value; value = tmp; } iterator_traits<InputIterator>::value_type tmp = *first; *first = *last; *last = tmp; return ++result; } template<class InputIterator, class OutputIterator, class binaryOp> OutputIterator ajacent_difference(InputIterator first, InputIterator last, OutputIterator result, binaryOp binary_op) { if (first == last) { return result; } *result = *first; // 记录第一个元素 iterator_traits<InputIterator>::value_type value = *first; // 利用特性萃取机取出value_type的类型 while (++first != last) { iterator_traits<InputIterator>::value_type tmp = *first; *++result = binary_op(tmp, value); // 以用户自定义的方式计算相邻两个元素的值,并赋给result value = tmp; } return ++result; } #pragma endregion #pragma region inner_product /* inner_product能够计算[ first1, last1 ] 和 [ fisrt2, first2 + ( last1 - fisrt1 ) ] 的一般内积(generalied inner product) 必须提供初值,确保 [ fisrt, last ] 为空时,仍有明确定义 */ template<class InputIterator1,class InputIterator2,class T> T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init) { for (; first1 != last1; ++first1, ++first2) { init = init + (*first1) * (*first2); // 计算内积 } return init; } template<class InputIterator1, class InputIterator2, class T, class binaryOp1, class binaryOp2> T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, binaryOp1 binary_op1, binaryOp2 binary_op2) { for (; first1 != last1; ++first1, ++first2) { init = binary_op1(init, binary_op2(*first1, *first2)); // 根据用户自定义的函数:binary_op1、binary_op2,计算内积 } return init; } #pragma endregion #pragma region partial_sum /* partial_sum用来计算局部总和,它会将 *first 赋值给 *result ,将 *first和 *(first + 1)的和赋值给 *( result + 1 ), 以此类推,注意,result 可以等于 first,这使得我们得以完成就地计算。 */ template<class InputIterator, class OutputIterator> OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result) { if (first == last) { return result; } *result = *first; iterator_traits<InputIterator>::value_type value = *first; while (++first != last) { value = value + *first ; // 值的累加 *++result = value ; } return ++result ; } template<class InputIterator, class OutputIterator, class binaryOp> OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result, binaryOp binary_op) { if(first == last) { return result; } *result = *first; iterator_traits<InputIterator>::value_type value = *first; while(++first != last) { value = binary_op( value, *first ) ; // 以用户指定的方法累加值 *++result = value ; } return ++result ; } #pragma endregion #pragma region power /* 计算某数的 n 次幂 */ template<class T, class Integer> inline T power(T x, Integer n) { return power(x, n, multiplies<T>()) ; } template<class T, class Integer, class MonoidOp> T power(T x, Integer n, MonoidOp op) { while ((n & 1) == 0) { n = n >> 1 ; x = op(x, x) ; } T result = x ; n = n >> 1 ; while (n != 0) { x = op(x, x) ; if ((n & 1) != 0) { result = op(result, x) ; } n = n >> 1 ; } return result ; } #pragma endregion } #endif
3.测试
测试环节的主要内容已在注释中说明test_algorithms_numeric.cpp
/******************************************************************* * Copyright(c) 2016 Chen Gonghao * All rights reserved. * * chengonghao@yeah.net * * 文件内容:cghStl_numeric.h 中的数值算法的测试 ******************************************************************/ #include "stdafx.h" #include "cghVector.h" #include "cghStl_numeric.h" #include <iterator> using namespace::std; int _tmain(int argc, _TCHAR* argv[]) { using namespace::CGH; std::cout << "创建一个vector,依次 puah_back 1、2、3、4、5" << endl << endl; cghVector<int> test; test.push_back(1); test.push_back(2); test.push_back(3); test.push_back(4); test.push_back(5); ostream_iterator<int> oite(cout, " "); // ostream_iterator<int>是一个迭代器,把ostream_iterator<int>绑定到cout,作为输出使用 std::cout << "******************测试 accumulate 算法************************" << endl << endl; cout << "缺省采用plus累加:1 + 2 + 3 + 4 + 5 = "; cout << accumulate(test.begin(), test.end(), 0) << endl << endl; cout << "用户指定 minus 函数:-1 - 2 - 3 - 4 - 5 = "; cout << accumulate(test.begin(), test.end(), 0, minus<int>()) << endl << endl; std::cout << "******************测试 ajacent_difference 算法************************" << endl << endl; cout << "默认情况下,计算 1、2、3、4、5 两两之间的差值:"; ajacent_difference(test.begin(), test.end(), oite); cout << endl << endl; cout << "用户指定 plus 函数,计算 1、2、3、4、5 两两之间的差值,再加 1:"; ajacent_difference(test.begin(), test.end(), oite, plus<int>()); cout << endl << endl; std::cout << "******************测试 inner_product 算法************************" << endl << endl; cout << "1×1 + 2×2 + 3×3 + 4×4 + 5×5 = "; cout << inner_product(test.begin(), test.end(), test.begin(), 0); cout << endl << endl; cout << "-( 1+1 ) - ( 2+2 ) - ( 3+3 ) - ( 4+4 ) - ( 5+5 ) = "; cout << inner_product(test.begin(), test.end(), test.begin(), 0, minus<int>(), plus<int>()); cout << endl << endl; std::cout << "******************测试 partial_sum 算法************************" << endl << endl; cout << "默认情况下,计算 第 n 个新元素是前 n 个旧元素的相加总计:"; partial_sum(test.begin(), test.end(), oite); cout << endl << endl; cout << "用户指定 minus 函数:"; partial_sum(test.begin(), test.end(), oite, minus<int>()); cout << endl << endl; std::cout << "******************测试 power 算法************************" << endl << endl; cout << "默认情况下,计算 10 的 3 次方:"; cout << power(10, 3) << endl ; cout << endl; cout << "用户指定 plus 函数,计算 10 + 10 + 10:"; cout << power(10, 3, plus<int>()) << endl ; cout << endl; system("pause"); return 0; }
结果如下图所示:
相关文章推荐
- 深入浅出UML类图
- 莫比乌斯函数
- KMP算法(next 数组讲解)
- Struts2的动态调用Action方法和默认Action
- 安卓控件点击动画(点击后产生波纹效果)
- 数据库 硬解析
- 一张图看Google MVP设计架构
- 折半查找(二分法)
- Java中的异常 Exception
- 二分算法~~~大综合
- SharedPreferences获取时报空指针异常,以及普通类中使用SharedPreferences存储数据
- -------------GetObject详解
- Python机器学习开发环境搭建和GraphLab Create安装
- PAT-天梯赛-L1-019. 谁先倒
- 单例模式
- c++第六次作业
- JAVA 对象引用,以及对象赋值
- html (1)
- linux--redis的安装和配置和开启多个端口
- PHP 实现“贴吧神兽”验证码