zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    操作系统-进程(1)进程与进程调度
    算法-图(6)广度优先遍历图
    网络摄像头RTSP流媒体协议视频平台EasyNVR如何进行延迟测试?
    【方案搭建】如何通过RTSP协议视频平台EasyNVR架设智慧城市实景终端展现方案?
    【解决方案】如何通过RTSP流媒体协议视频平台EasyNVR搭建智慧景区远程视频监管平台?
    7-12 排序 (25分)
    7-36 社交网络图中结点的“重要性”计算 (30分)-floyd最短路径
    7-35 城市间紧急救援 (25分)-dijkstra最短路径
    7-34 任务调度的合理性 (25分)--拓扑排序
    7-33 地下迷宫探索 (30分)--DFS
  • 原文地址:https://www.cnblogs.com/lvpengms/p/1663078.html
Copyright © 2011-2022 走看看