Peng Lv

毋意,毋必,毋固,毋我。 言必行,行必果。

导航

C++STL算法分析之:变易算法

现在看看stl中的变易算法

stl的变易算法很多,有三十个左右,现在只看看较常用的几个算法:copy,copy_backward,swap,iter_swap,swap_ranges,transform,replace_if,fill,fill_n,generate,generate_n,remove,
reverse,reverse_copy.

copy():
区间复制函数,将原区间内的元素一次复制到目的区间,三个参数是first,last,result,其中的result是目的区间的首地址,源码如下

template <class _InputIter, class _OutputIter, class _Distance>
inline _OutputIter __copy(_InputIter __first, _InputIter __last,
_OutputIter __result,
input_iterator_tag, _Distance
*)
{
  for ( ; __first != __last; ++__result, ++__first)
  
*__result = *__first;
  return __result;
}

 

 


copy_backward():
与copy算法相似,也是将原区间内的元素一次复制到目的区间,但元素的复制顺序是从后向前的,但要注意你所输入的result是目的区间的结束位置,所以,copy_backward和copy的结果是一样的,只不过是内部的实现细节不一样罢了,源码如下:

template <class _BidirectionalIter1, class _BidirectionalIter2,
class _Distance>
inline _BidirectionalIter2 __copy_backward(_BidirectionalIter1 __first,
_BidirectionalIter1 __last,
_BidirectionalIter2 __result,
bidirectional_iterator_tag,
_Distance
*)
{
  while (__first != __last)
  
*--__result = *--__last;
  return __result;
}

 

 

swap():
这个不用多说了,交换元素(这两个元素是以引用的形式传进来的):

template <class _Tp>
inline
void swap(_Tp& __a, _Tp& __b) {
  _Tp __tmp
= __a;
  __a
= __b;
  __b
= __tmp;
}

 

 


iter_swap():
函数是迭代器元素交换,参数是两个迭代器指针,注意:数据必须是可交换的:

template <class _ForwardIter1, class _ForwardIter2, class _Tp>
inline
void __iter_swap(_ForwardIter1 __a, _ForwardIter2 __b, _Tp*) {
  _Tp __tmp
= *__a;
  *__a = *__b;
  *__b = __tmp;
}

template
<class _ForwardIter1, class _ForwardIter2>
inline
void iter_swap(_ForwardIter1 __a, _ForwardIter2 __b) {
  __iter_swap(__a, __b, __VALUE_TYPE(__a));
}

 

 


swap_ranges():
顾名思意,他的作用是将原区间与目的区间的元素作交换,当然前提是元素必须是可交换的,有三个参数:first,last,result,其中result是目的区间的首地址,源码如下:

template <class _ForwardIter1, class _ForwardIter2>
_ForwardIter2 swap_ranges(_ForwardIter1 __first1, _ForwardIter1 __last1,
_ForwardIter2 __first2) {
  for ( ; __first1 != __last1; ++__first1, ++__first2)
   iter_swap(__first1, __first2);
  return __first2;
}

 

 


可以看出,他是调用了iter_swap()的(废话)

transform():
这个函数非常有用,可以替代你做不少复杂的工作,目的是将原区间的元素依次通过操作的到目的元素,这些结果是要存放到目的区间的,他有两个实现(一)op为一元操作符,故只能接受一个参数,transform的四个参数依次是first,last,result,op其中result是目的区间的首地址,(二)op为二元操作符,故原函数需要多一个参数,五个参数依次是:first,last,first,result,op,第三个first是第二个区间的首地址,result是目的区间的首地址,op为二元操作符,好了,看看源码:

template <class _InputIter, class _OutputIter, class _UnaryOperation>
_OutputIter transform(_InputIter __first, _InputIter __last,
_OutputIter __result, _UnaryOperation __opr) {
  for ( ; __first != __last; ++__first, ++__result)
  
*__result = __opr(*__first);
  return __result;
}

template
<class _InputIter1, class _InputIter2, class _OutputIter,
class _BinaryOperation>
_OutputIter transform(_InputIter1 __first1, _InputIter1 __last1,
_InputIter2 __first2, _OutputIter __result,
_BinaryOperation __binary_op) {
  for ( ; __first1 != __last1; ++__first1, ++__first2, ++__result)
  
*__result = __binary_op(*__first1, *__first2);
  return __result;
}

 

 


源码其实不难的,很容易就理解.


replace():
替换函数,将原区间内为old的元素全部替换为new元素,old和new是需要函数参数提供的:

template <class _ForwardIter, class _Tp>
void replace(_ForwardIter __first, _ForwardIter __last,
const _Tp& __old_value, const _Tp& __new_value) {
  for ( ; __first != __last; ++__first)
  
if (*__first == __old_value)
    
*__first = __new_value;
}

 

 


replace_if():
很容易理解,这个函数将原区间内满足一元谓词判断的元素全部替换为new元素:

template <class _ForwardIter, class _Predicate, class _Tp>
void replace_if(_ForwardIter __first, _ForwardIter __last,
_Predicate __pred,
const _Tp& __new_value) {
  for ( ; __first != __last; ++__first)
  
if (__pred(*__first))
    
*__first = __new_value;
}

 

 


fill():
填充函数,将原区间全部填满你所指定的元素,源码如下:

template <class _ForwardIter, class _Tp>
void fill(_ForwardIter __first, _ForwardIter __last, const _Tp& __value) {
  for ( ; __first != __last; ++__first)
  
*__first = __value;
}

 

fill_n()
也是填充,是填满[first,first+n]区间内的元素,源码如下:

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

 

 

generate()和generate_n():
两个函数都是生成函数,用指定的生成器(函数)来填满指定区间,为了便于说明,先看看两个函数的源码,之所以把这两个函数放到一起,是因为他们长的太像了,一起讨论方便:

template <class _ForwardIter, class _Generator>
void generate(_ForwardIter __first, _ForwardIter __last, _Generator __gen) {
  for ( ; __first != __last; ++__first)
  
*__first = __gen();
}

template
<class _OutputIter, class _Size, class _Generator>
_OutputIter generate_n(_OutputIter __first, _Size __n, _Generator __gen) {
  for ( ; __n > 0; --__n, ++__first)
  
*__first = __gen();
  return __first;
}

其中的一句话:*__first = gen(),可以看出,gen()函数是没有参数的,所以如果没有一个关于gen()的全局变量,gen()函数生成的结果是一样的,所以做好对gen()检查好了再用,不然有可能整个区间的元素是一样的。


remove_copy():
将原区间中不等于指定value的元素复制到目的区间,源码如下:

template <class _InputIter, class _OutputIter, class _Tp>
_OutputIter remove_copy(_InputIter __first, _InputIter __last,
_OutputIter __result,
const _Tp& __value) {
  for ( ; __first != __last; ++__first)
  
if (*__first != __value) {
     
*__result = *__first;
    
++__result;
   }
  return __result;
}


remove_copy_if():
这个函数将remove_copy中的value替换为一个谓词判断,只有不满足谓词判断的元素才会被复制到目的区间内,源码如下:

template <class _InputIter, class _OutputIter, class _Predicate>
_OutputIter remove_copy_if(_InputIter __first, _InputIter __last,
_OutputIter __result, _Predicate __pred) {
  for ( ; __first != __last; ++__first)
  
if (!__pred(*__first)) {
    
*__result = *__first;
    
++__result;
   }
  return __result;
}

 

remove():
这个算法是将容器中等于value的元素全部去掉,同样是先看看源码,在对他作分析:

_ForwardIter remove(_ForwardIter __first, _ForwardIter __last,
const _Tp& __value) {
  __first
= find(__first, __last, __value);
  _ForwardIter __i
= __first;
  return __first == __last ? __first
: remove_copy(
++__i, __last, __first, __value);
}


其中先找出第一个满足value的值的位置,再作判断,然后调用remove_copy()函数将不等于value的元素复制到新的区间上,可以看到,无论是空间或者是时间,这个算法的执行都不怎么好,remove_copy()操作浪费了太多的时间和空间,不过考虑到他的通用性,这个函数还是不错的。


reverse():
函数的功能是翻转指定区间的全部元素,算法思想很简单就能想到,不过源码写的很有技巧性,看后可以让人眼前一亮的感觉,源码分析:

template <class _BidirectionalIter>
void __reverse(_BidirectionalIter __first, _BidirectionalIter __last,
bidirectional_iterator_tag) {
  while (true)
  
if (__first == __last || __first == --__last)
    
return;
  
else
     iter_swap(__first
++, __last);
}


其中对first,last的操作可以说是很的巧妙了,多分析体会一下还是不错的。


reverse_copy():
不对原区间的元素进行操作,而是将其翻转输出到指定的目的区间,源码如下:

template <class _BidirectionalIter, class _OutputIter>
_OutputIter reverse_copy(_BidirectionalIter __first,
_BidirectionalIter __last,
_OutputIter __result) {
  while (__first != __last) {
  
--__last;
  
*__result = *__last;
  
++__result;
  }
  return __result;
}

 

posted on 2010-02-03 23:02  Lvpengms  阅读(678)  评论(0编辑  收藏  举报