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;
}
结果如下图所示:
本文介绍了STL中非质变算法的数值部分,包括accumulate、adjacent_difference、inner_product、partial_sum和power的实现与测试。这些算法在cghSTL版本中详细实现,通过VS2013编译,并提供了测试用例以验证正确性。

475

被折叠的 条评论
为什么被折叠?



