STL常用算法: remove,remove_if,remove_copy,remove_copy_if,remove系列算法和partition的区别...

下面我要介绍的是STL算法中,用来进行按条件除去容器内元素的通用算法,也就是所有容器都适用的方法.

#include <iostream>
#include <algorithm>
#include <functional>
#include <list>
using namespace std;

template <typename T>
class Print
{
public:
    void operator()(T a)
    {
        cout << a << " ";
    }
};

int main()
{

    list<int> s = {1,9,5,4,2,6,5,7};
    //remove算法,除去使第三个参数的值为true的元素.
    //注意,不管是什么算法,是不可能对原容器的元素的数量进行改变的,换句话说,就是算法不可能对容器进行增加元素或者删除元素的操作,所以remove算法只是把原容器的元素进行了筛选重组了而已,元素的数量还是原来的数量.
    list<int>::iterator pos = remove(s.begin(), s.end(), 5);
    for_each(s.begin(), s.end(), Print<int>());//1 9 4 2 6 7 5 7
    cout << endl;

    //容器内元素的增减只能通过容器自身所带的函数,比如:erase()或insert(),addpend()等等.
    s.erase(pos,s.end());
    for_each(s.begin(),s.end(),Print<int>());//1 9 4 2 6 7
    cout << endl;

    system("pause");
    return 0;
}

下面是remove的实现,当然跟SGI STL版本的源码不同,它直接用调用了remove_copy算法,但我们还没介绍到,我觉得这样的实现更方便理解.

template <typename T, typename V>
T myRemove(T first, T last, V value)
{
    T temp = first;
    while (temp != last)
    {
        //把值不同的元素给赋值到原容器的头开始,也就是第一个元素开始重新赋值,所以原容器最后会留下残余,当然这很好解决.看返回值.
        if (*temp != value)
        {
            *first = *temp;
            first++;
        }
        temp++;
    }
    //我们返回了原容器准备被继续赋值的下一个迭代器,也就是相当于知道了被赋值元素的个数,因为容器的erase()成员函数参数是迭代器,所以还是返回迭代器比较方便.
    return first;
}

remove解决后,就是remove_copy算法了,这个算法比较常用,我就不举例子了,直接写它的实现代码了:

//其实并没有什么不同,只是赋值给了别的容器.
//注意,凡是带copy的算法,拷贝进元素的容器必须要先resize足够的空间,否则当赋值时是会报错的!!!
template<typename T, typename V>
T myRemove_copy(T first, T last, T new_first, V value)
{
    while (first != last)
    {
        if (*first != value)
        {
            *new_first = *first;
            new_first++;
        }
        first++;
    }
    return new_first;
}

又到了remove_if算法了,其实是否有if,就是看你对元素的要求了,如果只是单纯删除某个元素,就用不到if了,当然也不是不能用…只是小题大做,浪费时间而已,如果要对容器内的元素进行区间的操作,也就是涉及到多个元素的操作,那么基本都要带if了…而且就和实现也没什么俩样,只是多了个函数的形式来取值.下面是remove_if的例子和剩下的remove算法实现.

#include <iostream>
#include <algorithm>
#include <functional>
#include <list>
using namespace std;

template <typename T>
class Print
{
public:
    void operator()(T a)
    {
        cout << a << " ";
    }
};

int main()
{
    list<int> s = { 1, 9, 5, 4, 2, 6, 5, 7 };

    //第三个参数可以看成是:如果元素>5,则返回true,否则返回false,这是个仿函数和配接器的配套使用.只能用于简单的操作,一些比较复杂的东西还是要自己去定制一个模板类,去重载()操作符滴...
    list<int>::iterator pos = remove_if(s.begin(), s.end(), bind2nd(greater<int>(), 5));
    for_each(s.begin(), s.end(), Print<int>());// 1 5 4 2 5 6 5 7
    cout << endl;

    s.erase(pos, s.end());
    for_each(s.begin(), s.end(), Print<int>());// 1 5 4 2 5
    cout << endl;

    system("pause");
    return 0;
}

remove_if和remove_copy_if的实现.

template <typename T, typename C>
T myRemove_if(T first, T last,C function)
{
    T temp = first;
    while (temp != last)
    {
        if (!function(*temp))
        {
            *first = *temp;
            first++;
        }
        temp++;
    }
    return first;
}


template <typename T, typename C>
T myRemove_copy_if(T first, T last,T new_first, C function)
{
    while (first != last)
    {
        if (!function(*first))
        {
            *new_first = *first;
            new_first++;
        }
        first++;
    }
    return new_first;
}

今天介绍的也挺多的了,明天会介绍下partition和stable_partition…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值