STL源码剖析学习十五:算法之其他算法

寻找相等的相邻元素

adjacent_find(first, last)
{
    if(first == last)
        return last;
    ForwardIterator next = first;
    while(++next != last)
    {
        if(*next == *first)
            return first;
        first = next;
    }
    return last;
}

 

 

统计与value元素相等的元素的个数

template <class InputIterator, class T>
typename iterator_traits<InputIterator>::difference_type
count(first, last, value)
{
    //关键在于计数器的声明
    typename iterator_traits<InputIterator>::difference_type n = 0;
    for(; first!=last; ++first)
    {
        if(*first == value)
            ++n;
    }
    return n;
}

count_if提供一个仿函数用来判断两个元素相等的条件

 

 

查找元素

find(first, last, value)
{
    while(first!=last && *first!=value)
        ++first;
    return first;
}

find_if提供一个仿函数用来判断两个元素相等的条件

 


在序列一中查找序列2的最后一次的出现点
又用到了双层迭代器的架构,令函数调用过程中产生迭代器类型的临时对象,再利用编译器的参数推导机制自动调用某个对应函数
上层函数一般称为分派函数

find_end(first1, last1, first2, last2)
{
    typedef typename iterator_traits<ForwardIterator1>::iterator_category category1;
    typedef typename iterator_traits<ForwardIterator1>::iterator_category category1;
    return __find_end(first1, last1, first2, last2, categroy1(), category2());
}


__find_end(first1, last1, first2, last2, forward_iterator_tag, forward_iterator_tag)
{
    if(first2 == last2)
        return last1;
    else
    {
        ForwardIterator1 result = last1;
        while(1)
        {
            //用search来查找符合条件的区间
            ForwardIterator1 new_result = search(first1, last1, first2, last2);
            if(new_result == last1)
                return result;//没有找到就返回
            else//如果找到就记录下本次查找的结果,并且调整迭代器准备下一次查找
            {
                result = new_result;
                first = new_result;
                ++first;
            }
        }
    }
}

 


查找序列2内任意一个元素在序列1内第一次出现的位置

find_first_of(first1, last1, first2, last2)
{
    for(; first!=last1; ++first1)
    {
        for(ForwardIterator ite=first2; ite!=last2; ++ite)
        {
            if(*ite == *first)
                return first;
        }
    }
    return last1;
}

 

 

将仿函数f实行于区间内的每一个元素上,f不可以改变元素的内容,要修改元素内容用transform
//其实f是可以修改元素内容的,只要在定义仿函数时将传入元素的引用就可以了

for_each(first, last, f)
{
    for(; first!=last; ++first)
        f(*first);
    return f  //返回的是仿函数
}

 


将仿函数f作用于每一个元素并且将结果输出到另一个序列
如果目的迭代器指向源序列的起点,那么他就会替代原来的元素

transform(first, last, result, op)
{
    for(; first!=last; ++first, ++result)
        *result = op(*first);
    return result  //返回的是结果序列的最后一个元素的下一位置
}

 

 

将仿函数gen的运算结果写在区间内

generate(first, last, gen)
{
    for(; first!=last; ++first)
        *first = gen();
}

 

给个仿函数写法的例子

class even_by_two
{
    public:
        int operator()()const
        { return _x += 2; }
    private:
        static _x;
}
int even_by_two::_x = 0;

generate_n将结果填写到前n个位置中

 


判断序列1是否包含序列2,必须用于有序区间

includes(first1, last1, first2, last2)
{
    while(first1!=last1 && first2!=last2)
    {
        if(*first1<*first2)
        {
            ++first1;
        }
        else if(*first2<*first1)
        {
            return false;
        }
        else
        {
            ++first1;
            ++first2;
        }
    }
    return first2 == last2 //保证序列2中的元素都被遍历到
}

如果要提供comp比较函数来判断两个元素是否相等
则必须符合
if(comp(*first1, *first2))
.......
else if(comp(*first2, *first1))
......
else
....
用这种方式可以判断两个元素的大于小于等于,否则就会出错

 

 


合并两个区间,并且写到新的区间中,作用于有序区间(类似于求交集)

merge(first1, last1, first2, last2, result)
{
    while(first1!=last1 && first2!=last2)
    {
        if(*first1 < *first2)
        {
            *result = *first1;
            ++first1;
        }
        else if(*first2 < *first1)
        {
            *result = *first2;
            ++first2;
        }
        else
        {
            *result = *first1;
            ++first1;
            ++first2;
        }
        ++result;
    }
    return copy(first1, last1, copy(first2, last2));
}

 

 

 

将区间内的元素重新排列,用仿函数pred判定为为true的元素都放在前段,false的元素都放在后段
不保证元素之间的相对位置,如果需要,就用stable_partition

partition(first, last, pred)
{
    while(1)
    {
        while(1)
        {
            if(first == last)
                return first;
            else if( pred(*first) )
                ++first;
            else
                break;
        }
        --last;
        while(1)
        {
            if(first == last)
                return first;
            else if( !pred(*last) )
                --last;
            else
                break;
        } 
        iter_swap(first, last);
        ++first;
    }
}

 

 

移除(但不是删除)
把每一个与value不相等的元素轮番复制给first之后的空间,
返回值指向重新整理后的最后元素的下一个位置。
如果要从实际上删除则调用erase
array不适用remove,因为其尺寸无法缩小,最好使用remove_copy和remove_copy_if

remove(first, last, value)
{
    first = find(first, last, value);
    //找到第一个相等的元素的位置,从该位置之后的一个位置开始拷贝
    //利用remove_copy允许新旧容器重叠的特性进行移除操作
    ForwardIterator next = first;
    return first == last? first: remove_copy(++next, last, first, value);
}

 

 


remove_if提供一个仿函数可以判断元素值是否跟value相等

移除区间中和value相等的元素,并把结果拷贝到新的容器中,新旧容器可以重叠

remove_copy(first, last, result, value)
{
    for(; first!=last; ++first)
    {
        if(*first != value)
            *result = *first;
        ++result;
    }
    return first;
}

remove_copy_if提供一个仿函数可以判断元素值是否跟value相等

 

待续~~~~~~~~

posted @ 2012-04-27 11:31  w0w0  阅读(212)  评论(0)    收藏  举报