15数值算法(numeric)

1、算法概述

算法,问题之解法也。再好的编程技巧,也无法让一个笨拙的算法起死回生。选择了错误的算法,便注定了失败的命运。

STL中极具复用价值的70余个STL算法,包括赫赫有名的排序、查找、排列组合算法,以及用于数据移动、复制、删除、比较、组合、运算等算法。

(1)质变算法——会改变操作对象的值

质变算法是指运算过程中会更改区间内迭代器所指的元素内容。例如拷贝(copy)、互换(swap)、替换(replace)、填写(fill)、删除(remove)、排列组合(permutation)、分割(partition)、随机重排(random shuffling)、排序(sort)等算法。

(2)非质变算法——不会改变操作对象的值

非质变算法是指运算过程中不会更改区间内迭代器所指的元素内容。例如查找(find)、匹配(search)、计数(count)、巡防(for_each)、比较(equal,mismatch)、寻找极值(max,min)等算法。

2、数值算法

欲使用数值算法,客户端必须包含表头<numeric>,SGI将数值算法实现于<stl_numeric.h>文件中。常见的数值算法有accumulate、adjacent_difference、inner_product、partial_sum、power、iota等。

3、accumulate

算法accumulate用来计算init和[first,last)内所有元素的总和。注意:一定要提供一个初始值init,这么做是当[first,last)区间为空时仍能获得一个明确定义的值。

template <class InputIterator, class T>
T accumulate(InputIterator first, InputIterator last, T init) {
  for ( ; first != last; ++first)
    init = init + *first;
  return init;
}

template <class InputIterator, class T, class BinaryOperation>
T accumulate(InputIterator first, InputIterator last, T init,
             BinaryOperation binary_op) {
  for ( ; first != last; ++first)
    init = binary_op(init, *first);
  return init;
}

4、adjacent_difference

算法adjacent_difference用来计算[first,last)中相邻元素的差额。它会将*first赋值给result,并针对[first+1,last)内的每个迭代器i,将*i-*(i-1)之值赋值给*(result+(i-first))。如果采用就地(in place)运算方式,也就是令result等于first,在这种情况下它是一个质变算法。

第一个版本使用operator-来计算差额,第二版本采用外界提供的二元仿函数。第一版本针对[first+1,last)中的每个迭代器i,将*i-*(i-1)之值赋值给*(result+(i-first)),第二个版本则是将binary_op(*i,*(i-1))的运算结果赋值给*(result+(i-first))。

template <class InputIterator, class OutputIterator, class T>
OutputIterator __adjacent_difference(InputIterator first, InputIterator last,
                                     OutputIterator result, T*) {
  T value = *first;
  while (++first != last) {
    T tmp = *first;
    *++result = tmp - value;
    value = tmp;
  }
  return ++result;
}

template <class InputIterator, class OutputIterator>
OutputIterator adjacent_difference(InputIterator first, InputIterator last,
                                   OutputIterator result) {
  if (first == last) return result;
  *result = *first;
  return __adjacent_difference(first, last, result, value_type(first));
}

template <class InputIterator, class OutputIterator, class T,
          class BinaryOperation>
OutputIterator __adjacent_difference(InputIterator first, InputIterator last,
                                     OutputIterator result, T*,
                                     BinaryOperation binary_op) {
  T value = *first;
  while (++first != last) {
    T tmp = *first;
    *++result = binary_op(tmp, value);
    value = tmp;
  }
  return ++result;
}

template <class InputIterator, class OutputIterator, class BinaryOperation>
OutputIterator adjacent_difference(InputIterator first, InputIterator last,
                                   OutputIterator result,
                                   BinaryOperation binary_op) {
  if (first == last) return result;
  *result = *first;
  return __adjacent_difference(first, last, result, value_type(first),
                               binary_op);
}

5、inner_product

算法inner_product能够计算[first1,last1)和[first2,first2+(last1-first1))的一般内积。注意:一定要提供一个初始值init,这么做是当[first,last)区间为空时仍能获得一个明确定义的值。

第一个版本会将两个区间的内积结果加上init,先将结果初始化为init,然后针对[first1,last1)的每个迭代器i,由头至尾依序执行result=result+(*i)*(*(first2+(i-first1)))。第二版本是以外界提供的仿函数来取代operator+和operator*,先将结果初始化为init,然后针对[first1,last1)的每个迭代器i,由头至尾依序执行result=binary_op1(result,binary_op2(*i,*(first2+(i-first1)))。

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 BinaryOperation1, class BinaryOperation2>
T inner_product(InputIterator1 first1, InputIterator1 last1,
                InputIterator2 first2, T init, BinaryOperation1 binary_op1,
                BinaryOperation2 binary_op2) {
  for ( ; first1 != last1; ++first1, ++first2)
    init = binary_op1(init, binary_op2(*first1, *first2));
  return init;
}

6、partial_sum

算法partial_sum用来计算局部总和。如果采用就地(in place)运算方式,也就是令result等于first,在这种情况下它是一个质变算法。运算中的总和首先初始化为*first,然后赋值给*result。对于[first+1,last)中的每个迭代器i,从头至尾依序执行sum=sum+*i或sum=binary_op(sum,*i),然后再将sum赋值给*(result+(i-first))。本算法返回输出区间的最尾端位置:result+(last-first)。

template <class InputIterator, class OutputIterator, class T>
OutputIterator __partial_sum(InputIterator first, InputIterator last,
                             OutputIterator result, T*) {
  T value = *first;
  while (++first != last) {
    value = value + *first;
    *++result = value;
  }
  return ++result;
}

template <class InputIterator, class OutputIterator>
OutputIterator partial_sum(InputIterator first, InputIterator last,
                           OutputIterator result) {
  if (first == last) return result;
  *result = *first;
  return __partial_sum(first, last, result, value_type(first));
}

template <class InputIterator, class OutputIterator, class T,
          class BinaryOperation>
OutputIterator __partial_sum(InputIterator first, InputIterator last,
                             OutputIterator result, T*,
                             BinaryOperation binary_op) {
  T value = *first;
  while (++first != last) {
    value = binary_op(value, *first);
    *++result = value;
  }
  return ++result;
}

template <class InputIterator, class OutputIterator, class BinaryOperation>
OutputIterator partial_sum(InputIterator first, InputIterator last,
                           OutputIterator result, BinaryOperation binary_op) {
  if (first == last) return result;
  *result = *first;
  return __partial_sum(first, last, result, value_type(first), binary_op);
}

7、power

power算法由SGI专属,并不在STL标准之列。它是用来计算某数的n幂次方。运算类型可由外界指定,如果指定为乘法,那就是乘幂,当n>=0时返回x^n。

这里使用了快速幂算法,简化后算法:

template <class T, class Integer, class MonoidOperation>
T power(T x, Integer n, MonoidOperation op) {
  if (n == 0)
    return identity_element(op);
  else {
    T result = 1;
    while (n != 0) {
      if ((n & 1) != 0)
        result = op(result, x);
      x = op(x, x);
      n >>= 1;
    }
    return result;
  }
}
template <class T, class Integer, class MonoidOperation>
T power(T x, Integer n, MonoidOperation op) {
  if (n == 0)
    return identity_element(op);
  else {
    while ((n & 1) == 0) {
      n >>= 1;
      x = op(x, x);
    }

    T result = x;
    n >>= 1;
    while (n != 0) {
      x = op(x, x);
      if ((n & 1) != 0)
        result = op(result, x);
      n >>= 1;
    }
    return result;
  }
}

template <class T, class Integer>
inline T power(T x, Integer n) {
  return power(x, n, multiplies<T>());
}

8、iota

iota算法由SGI专属,并不在STL标准之列。它用来设定某个区间的内容,使其内的每个元素从指定的value值开始,呈现递增状态。

template <class ForwardIterator, class T>
void iota(ForwardIterator first, ForwardIterator last, T value) {
  while (first != last) *first++ = value++;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值