Algorithm

clipboard.png

迭代器分类

clipboard.png

迭代器类型对算法的影响

clipboard.png

clipboard.png

clipboard.png

仿函数

  • STL各部分关系

clipboard.png

容器通过内存分配器分配空间;容器和算法因为迭代器而分离,算法通过迭代器访问容器;仿函数协助算法指定不同的策略;适配器套接仿函数。仿函数将某种"行为"作为算法的参数传给算法。

仿函数适配器(Function Adapter)

  • binder1st

给定一个vector,其元素为:[0,0,0,1,0],想要匹配到第一个非零元素。我们有find_if()的算法和not_equal_to的函数对象,根据这两个东西就可以实现我们的目的。然而,not_equal_to()(const T& a,const T&b),并不能接受一个参数;find_if()又是向最后一个函数对象直接给予一个引用作为参数,所以无法编译通过。为此使用binder1st来把其中的一个参数固定下来。

vector<int>::iterator it = find_if(v.begin(),v.end(),bind1st(not_equal_to<int>(),0));
  • binder2nd

clipboard.png

  • 为了这种机制的考虑,在所有的仿函数中都要有first_argument_type等这几个typedef。通常通过派生自binary_function<class Arg1,class Arg2,class Result>可以直接得到。
  • 例如 binder1st<not_equal_to<int>>(f,0)就代表生成一个函数对象func(x)=f(0,x);
  • 各种函数适配器都是以实例化后的仿函数的类型作为模板参数的类模板,这是函数适配器的重要标志。

迭代器适配器

  • reverse_iterator

clipboard.png

一些注意点

  1. 注意如果使用了诸如push(new Point(x,y))这种语法,必须要在删除容器之前遍历容器进行内存释放,否则就发生了内存泄露。
  2. 尽量用算法代替手写的循环,一方面是从效率的角度考虑,另一方面使用算法的这种方式更好地体现了面向对象的思想。
  3. 容器的size和capacity

Capacity是容器"占据"的空间,size是容器"使用"的空间。所以容器有可能占据了很大的空间然而并没有使用那一部分空间,那么这种情况下应该通过swap方法对容器进行缩小。

  1. 为什么建议在容器中放指针而不是对象?

1.拷贝的开销比较大。
2.如果存在继承,就会发生slicing。即由于保存的仅仅是基类对象,其留下的大小也就是基类对象的大小。如果存在继承关系时,若将派生类对象放入容器,则只会保留基类部分,派生类部分会丢失。这种方式体现出了C++中的多态性。

一些泛型算法

  • for_each
template<class _InIt,class _Fnl> inline

_Fnl for_each(_InIt _First, _InIt _Last, _Fnl _Func)

for_each就是把两个迭代器之间的对象实例扔给_Func作为唯一参数。注意,_Func不一定非得是函数对象(仿函数),直接传函数名或函数指针也是可以的。

  • find
template<class _InIt,class _Ty> inline

_Ty find(_InIt _First, _InIt _Last,const _Ty& _Val)

如果在左闭右开区间内找到了值为_Val的对象则返回该迭代器,否则返回器尾部迭代器。

  • find_if
template<class _InIt,class _Pr> inline

_Ty find(_InIt _First, _InIt _Last,const _Pr _Pred)

_Pr为一个函数名或者函数对象(仿函数)。如果在左闭右开区间内找到了的能使得这一对象返回真的,则返回该迭代器,否则返回器尾部迭代器。注意_Pr为单参,注意联合适配器的使用。

  • adjacent_find

    template <class ForwardIterator>
    
    ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last);
    

返回第一个遇到的两个连续相等的对象中,第一个对象的迭代器,如对于[0,1,2,3,3,4],则返回指向第一个3的迭代器。

template<class _InIt,class _Pr> inline

_Ty find(_InIt _First, _InIt _Last,const _Pr _Pred)

Adjacent的操作实际上是针对自己和后继进行的比较操作。除了默认的等于比较操作之外,也可以使用自定义的函数或仿函数。_Pred 具有两个参数,使用时会把连续的两个值分别作为第一参数和第二参数求真值。

  • find_first_of
template <class ForwardIterator1, class ForwardIterator2>

ForwardIterator1 find_first_of (ForwardIterator1 first1, ForwardIterator1 last1,

ForwardIterator2 first2, ForwardIterator2 last2);

 

template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>

ForwardIterator1 find_first_of (ForwardIterator1 first1, ForwardIterator1 last1,

ForwardIterator2 first2, ForwardIterator2 last2,

BinaryPredicate pred);

它是在两组区间内搜索是否有it1==it2,如果有就返回第一组区间内对象的迭代器。也可以使用自定义的双参函数进行比较。

  • count/count_if
template <class InputIterator, class T>

typename iterator_traits<InputIterator>::difference_type

count (InputIterator first, InputIterator last, const T& val);

返回左闭右开区间中值等于val的元素的个数。

类比find,count_if就是自己指定所想使用的函数。同样地,其为单参,要注意两对适配器的使用。

  • mismatch
template <class InputIterator1, class InputIterator2, class BinaryPredicate>

pair<InputIterator1, InputIterator2>

mismatch (InputIterator1 first1, InputIterator1 last1,

InputIterator2 first2, BinaryPredicate pred);

当不指定最后一个函数时,其作用是逐元素比对两个序列,返回指向第一个容器中的第一个不一致的迭代器。如果指定函数,则是需要返回值等于False。

  • equal
template <class InputIterator1, class InputIterator2, class BinaryPredicate>

bool equal (InputIterator1 first1, InputIterator1 last1,

InputIterator2 first2, BinaryPredicate pred);

当不指定最后一个函数时,其作用是检查两个容器内容是否完全相等。若指定最后一个函数,则是逐元素检查是否满足两两返回值均为True。

  • search
template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>

ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1,

ForwardIterator2 first2, ForwardIterator2 last2,

BinaryPredicate pred);

当不指定最后一个函数时,其作用是搜索前一个序列中是否存在和第二个序列相同的子序列;如果自定义判别函数,则是逐元素比对,搜索是否存在能够和第二个序列匹配的序列。返回值为第一个序列中匹配的位置,如果找不到则返回末位迭代器。


风斩冰华
27 声望12 粉丝

coding