STL 简单 <stl_numeric.h> 算法的实现

本文介绍了STL中非质变算法的数值部分,包括accumulate、adjacent_difference、inner_product、partial_sum和power的实现与测试。这些算法在cghSTL版本中详细实现,通过VS2013编译,并提供了测试用例以验证正确性。

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


 

结果如下图所示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值