现在看看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;
}