您的位置:首页 > 其它

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;
}


 

结果如下图所示:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: