C++STL algo

本文详细介绍了C++ Standard Template Library(STL)中的数值算法,包括Accumulate、Inner_product、Partial_sum、Adjacent_difference等函数的用法和源码解析,帮助读者深入理解STL算法的实现原理和应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SGI STL算法

数值算法(Numeric)

使用需包含文件<numeric>

Accumulate函数

功能:计算init和[first,last)内所有元素的总和,需要提供一个初始值init

使用:

Int ia[5] = {1,2,3,4,5};

Vector<int> iv(ia, ia+5);

Accumulate(iv.begin(), iv.end(), 0);

//15, 0+1+2+3+4+5

Accumulate(iv.begin(), iv.end(), 0, minux<int>());

//-15, 0-1-2-3-4-5

源码:

//版本1

template <class _InputIterator, class _Tp>

_Tp accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)

{

  for ( ; __first != __last; ++__first)

    __init = __init + *__first;

  return __init;

}

//版本2

template <class _InputIterator, class _Tp, class _BinaryOperation>

_Tp accumulate(_InputIterator __first, _InputIterator __last, _Tp __init,

               _BinaryOperation __binary_op)

{

  for ( ; __first != __last; ++__first)

    __init = __binary_op(__init, *__first);

  return __init;

}

Inner_product函数

功能:算法计算[first1,last1)和[first2,last2)的内积,需要提供初始值init

使用:

Int ia[5] = {1,2,3,4,5};

Vector<int> iv(ia, ia+5);

Inner_product(iv.begin(), iv.end(), iv.begin(), 10);

//65, 10+1*1+2*2+3*3+4*4+5*5

Inner_product(iv.begin(), iv.end(), iv.begin(), 10, minus<int>(), plus<int>());

//-20, 10-1+1-2+2-3+3-4+4-5+5

源码:

template <class _InputIterator1, class _InputIterator2, class _Tp>

_Tp inner_product(_InputIterator1 __first1, _InputIterator1 __last1,

                  _InputIterator2 __first2, _Tp __init)

{

  for ( ; __first1 != __last1; ++__first1, ++__first2)

    __init = __init + (*__first1 * *__first2);

  return __init;

}

//执行二元操作符

template <class _InputIterator1, class _InputIterator2, class _Tp,

          class _BinaryOperation1, class _BinaryOperation2>

_Tp inner_product(_InputIterator1 __first1, _InputIterator1 __last1,

                  _InputIterator2 __first2, _Tp __init,

                  _BinaryOperation1 __binary_op1,

                  _BinaryOperation2 __binary_op2)

{

  for ( ; __first1 != __last1; ++__first1, ++__first2)

    __init = __binary_op1(__init, __binary_op2(*__first1, *__first2));

  return __init;

}

Partial_sum函数

功能:算法partial_sum用来计算局部总和,它会将*first赋值给result,将*first和*(first+1)是和赋值给*(result+1)依此类推。

用法:

Int ia[5] = {1,2,3,4,5};

Vector<int> iv(ia, ia+5);

//迭代器绑定到cout,作为输出

Ostream_iterator<int> oite(cout, “”);

Partial_sum(iv.begin(), iv.end(), oite);

//1 3 6 10 15(第n个新元素是前n个旧元素的相加总计)

Partial_sum(iv.begin(), iv.end(), oite, minus<int>());

//1 -1 -4 -8 -13(第n个新元素是前n个旧元素的运算总计)

源码:

template <class _InputIterator, class _OutputIterator, class _Tp>

_OutputIterator

__partial_sum(_InputIterator __first, _InputIterator __last,

              _OutputIterator __result, _Tp*)

{

  _Tp __value = *__first;

  while (++__first != __last) {

    __value = __value + *__first;

    *++__result = __value;

  }

  return ++__result;

}

//将first的第一个值赋予个result的第一个值中,并且萃取出first的值类型

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

}

Adjacent_difference函数

功能:算法用来计算[first,last)中相邻元素的差额

用法:

Int ia[5] = {1,2,3,4,5};

Vector<int> iv(ia, ia+5);

Adjacent_difference(iv.begin(), iv.end(), oite);

//1 1 1 1 1(#1元素照旧,#n新元素等于#n旧元素-#n-1旧元素)

Adjacent_difference(iv.begin(), iv.end(), oite, plus<int>());

//1 3 5 7 9(#1元素照旧,#n新元素等于op(#n旧元素, #n-1旧元素))

源码:

template <class _InputIterator, class _OutputIterator, class _Tp>

_OutputIterator

__adjacent_difference(_InputIterator __first, _InputIterator __last,

                      _OutputIterator __result, _Tp*)

{

  _Tp __value = *__first;

  while (++__first != __last) {

    _Tp __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));

}

*Power函数

功能:函数为SGI专属,用来计算某数的n幂次方。这里指自己对自己进行某种运算,达n次,运算类型可由外界指定,如果指定为乘法,那就是乘幂。

用法:

Power(10, 3);//1000, 10*10*10

Power(10, 3, plus<int>());//30, 10+10+10

源码:

//注意:MonoidOperation必须满足结合律associative,但不满足交换律commutative。

template <class _Tp, class _Integer, class _MonoidOperation>

_Tp __power(_Tp __x, _Integer __n, _MonoidOperation __opr)

{

  if (__n == 0)

    return identity_element(__opr);

  else {

    while ((__n & 1) == 0) {

      __n >>= 1;

      __x = __opr(__x, __x);

    }

    _Tp __result = __x;

    __n >>= 1;

    while (__n != 0) {

      __x = __opr(__x, __x);

      if ((__n & 1) != 0)

        __result = __opr(__result, __x);

      __n >>= 1;

    }

    return __result;

  }

}

//版本二,以multiplies<_Tp>()操作调用版本一

template <class _Tp, class _Integer>

inline _Tp __power(_Tp __x, _Integer __n)

{

  return __power(__x, __n, multiplies<_Tp>());

}

*Itoa函数

功能:函数为SGI专属,用来设定某个区间的内容,使其每个元素从指定值value开始,呈现递增

源码:

//在 [first,last) 范围内內填入value, value+1, value+2...

template <class _ForwardIter, class _Tp>

void

iota(_ForwardIter __first, _ForwardIter __last, _Tp __value)

{

  while (__first != __last)

    *__first++ = __value++;

}

基本算法Algobase

Equal函数

功能:如果两个序列在[first,last)区间内相等,equal返回true,如果第二序列的元素比较多,多出来的元素不予考虑。因此,如果判断两个序列完全相等,必须先判断其元素个数是否相同。如果第二序列元素比第一序列少,则会造成不可预测的结果。

使用:

Int ia[9] = {0,1,2,3,4,5,6,7,8};

Vector<int> iv1(ia, ia+5);

Vector<int> iv2(ia, ia+9);

Equal(iv1.begin(), iv1.end(), iv2.begin()); //1,true

Equal(iv1.begin(), iv1.end(), &ia[3]); //0,false

//{0.1.2.3.4}小于{3,4,5,6,7}

源码:

//版本1

template <class _InputIter1, class _InputIter2>

inline bool equal(_InputIter1 __first1, _InputIter1 __last1,

                  _InputIter2 __first2) {

  for ( ; __first1 != __last1; ++__first1, ++__first2)

    if (*__first1 != *__first2)

      return false;

  return true;

}

//版本2

template <class _InputIter1, class _InputIter2, class _BinaryPredicate>

inline bool equal(_InputIter1 __first1, _InputIter1 __last1,

                  _InputIter2 __first2, _BinaryPredicate __binary_pred) {

  for ( ; __first1 != __last1; ++__first1, ++__first2)

    if (!__binary_pred(*__first1, *__first2))

      return false;

  return true;

}

Fill函数

功能:将[first,last)内的所有元素改填新值

使用:

Int ia[9] = {0,1,2,3,4,5,6,7,8};

Vector<int> iv1(ia, ia+5);

Fill(iv1.begin(0, iv1.end(), 9);

//区间内全部置9 //9 9 9 9 9

源码:

template <class _ForwardIter, class _Tp>

void fill(_ForwardIter __first, _ForwardIter __last, const _Tp& __value) {

  for ( ; __first != __last; ++__first)

    *__first = __value;

}

Fill_n函数

功能:将[first,last)内的前n个元素改填新值

使用:

Int ia[9] = {0,1,2,3,4,5,6,7,8};

Vector<int> iv1(ia, ia+5);

Fill_n(iv1.begin(), 3, 7); //从迭代器所指位置开始,填3个7

//7 7 7 3 4

如果n超越了容器的现有大小,由于每次迭代进行的是assignment操作,是一种overwrite操作,所以一旦操作区间超越了容器大小,就会造成不可预期的结果。解决办法之一是利用inserter()产生一个具有插入而非overwrite能力的迭代器,用法如下

Int ia[3] = {0,1,2};

Fill_n(inserter(iv, iv.begin(), 5, 7));

源码:

template <class _OutputIter, class _Size, class _Tp>

_OutputIter fill_n(_OutputIter __first, _Size __n, const _Tp& __value) {

  for ( ; __n > 0; --__n, ++__first)

    *__first = __value;

  return __first;

}

Iter_swap函数

功能:将两个ForwardIterators所指的对象对调

源码:

template <class _ForwardIter1, class _ForwardIter2>

inline void iter_swap(_ForwardIter1 __a, _ForwardIter2 __b) {

  __iter_swap(__a, __b, __VALUE_TYPE(__a));

}

template <class _ForwardIter1, class _ForwardIter2, class _Tp>

inline void __iter_swap(_ForwardIter1 __a, _ForwardIter2 __b, _Tp*) {

  _Tp __tmp = *__a;

  *__a = *__b;

  *__b = __tmp;

}

Lexicographical_compare函数

功能:以字典排列方式对两个序列[first1,last1)和[first2,last2)进行比较。对两个序列中对应位置上的元素进行比较,并持续到

  1. 某一组对应元素彼此不相等

同时达到last1和last2,两序列大小相同

到达last1或last2,两序列大小不同

如果出现*first1 < *first2,则返回true

如果出现*first2 < *first1,则返回false

如果直到循环结束,两个序列的值都相等

如果第一个序列比第二个序列短,则返回true

否则返回false(两个序列长度相等也返回false)

使用:

String stra1[] = {“Jamie”, “JJHou”, “Jason”};

String stra2[] = {“Jamie”, “JJhou”, “Jerry”};

Lexicographical_compare(stra1, stra+2, stra2, stra+2);

//1 (stra1小于stra2)

Lexicographical_compare(stra1, stra1+2, stra2, stra2+2, greater<string>());

//0 (stra1不大于stra2)

源码:

//版本1

template <class _InputIter1, class _InputIter2>

bool lexicographical_compare(_InputIter1 __first1, _InputIter1 __last1,

                             _InputIter2 __first2, _InputIter2 __last2) {

  for ( ; __first1 != __last1 && __first2 != __last2

        ; ++__first1, ++__first2) {

    if (*__first1 < *__first2)

      return true;

    if (*__first2 < *__first1)

      return false;

  }

  return __first1 == __last1 && __first2 != __last2;

}

//版本2

template <class _InputIter1, class _InputIter2, class _Compare>

bool lexicographical_compare(_InputIter1 __first1, _InputIter1 __last1,

                             _InputIter2 __first2, _InputIter2 __last2,

                             _Compare __comp) {

  for ( ; __first1 != __last1 && __first2 != __last2

        ; ++__first1, ++__first2) {

    if (__comp(*__first1, *__first2))

      return true;

    if (__comp(*__first2, *__first1))

      return false;

  }

  return __first1 == __last1 && __first2 != __last2;

}

//const unsigned char*原生指针特化版本

inline bool

lexicographical_compare(const unsigned char* __first1,

                        const unsigned char* __last1,

                        const unsigned char* __first2,

                        const unsigned char* __last2)

{

  const size_t __len1 = __last1 - __first1;

  const size_t __len2 = __last2 - __first2;

  const int __result = memcmp(__first1, __first2, min(__len1, __len2));

  return __result != 0 ? __result < 0 : __len1 < __len2;

}

//const signed char*原生指针特化版本

inline bool lexicographical_compare(const char* __first1, const char* __last1,

                                    const char* __first2, const char* __last2)

{

#if CHAR_MAX == SCHAR_MAX

  return lexicographical_compare((const signed char*) __first1,

                                 (const signed char*) __last1,

                                 (const signed char*) __first2,

                                 (const signed char*) __last2);

#else /* CHAR_MAX == SCHAR_MAX */

  return lexicographical_compare((const unsigned char*) __first1,

                                 (const unsigned char*) __last1,

                                 (const unsigned char*) __first2,

                                 (const unsigned char*) __last2);

#endif /* CHAR_MAX == SCHAR_MAX */

}

Max函数

功能:取两个对象中的较大值,版本2使用仿函数comp来判断大小

源码:

template <class _Tp>

inline const _Tp& max(const _Tp& __a, const _Tp& __b) {

  return  __a < __b ? __b : __a;

}

template <class _Tp, class _Compare>

inline const _Tp& max(const _Tp& __a, const _Tp& __b, _Compare __comp) {

  return __comp(__a, __b) ? __b : __a;

}

Min函数

功能:取两个对象中较小值,版本2使用仿函数comp来判断大小。

源码:

template <class _Tp>

inline const _Tp& min(const _Tp& __a, const _Tp& __b) {

  return __b < __a ? __b : __a;

}

template <class _Tp, class _Compare>

inline const _Tp& min(const _Tp& __a, const _Tp& __b, _Compare __comp) {

  return __comp(__b, __a) ? __b : __a;

}

Swap函数

功能:交换a和b的值

源码:

// template <class _Tp>

inline void swap(_Tp& __a, _Tp& __b) {

  _Tp __tmp = __a;

  __a = __b;

  __b = __tmp;

}

Mismatch函数

功能:用来比较两个序列,指出两者之间的第一个不匹配点,返回一对迭代器分别指向两序列中的不匹配点。如果第二序列的元素比第一序列多,多出来的元素忽略不计,如果第二序列的元素个数比第一序列少,会发生不可预期的行为。

使用:

Int ia[9] = {0,1,2,3,4,5,6,7,8};

Vector<int> iv1(ia, ia+5);

Vector<int> iv2(ia, ia+9);

*(mismatch(iv1.begin(), iv1.end(), iv2.begin()).first); //?

*(mismatch(iv1.begin(), iv1.end(), iv2.begin()).second); //5

//判断两个区间的第一个不匹配点,返回右两个迭代器组成的pair,上述应先判断迭代器是否不等于容器的end(),然后才可以做输出操作。

源码:

template <class _InputIter1, class _InputIter2>

pair<_InputIter1, _InputIter2> mismatch(_InputIter1 __first1,

                                        _InputIter1 __last1,

                                        _InputIter2 __first2) {

  while (__first1 != __last1 && *__first1 == *__first2) {

    ++__first1;

    ++__first2;

  }

  return pair<_InputIter1, _InputIter2>(__first1, __first2);

}

template <class _InputIte

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值