zoukankan      html  css  js  c++  java
  • STL之remove算法详解

    算法描述

    接口

    template<class ForwardIterator, class Type>
     ForwardIterator remove(
          ForwardIterator _First, 
          ForwardIterator _Last, 
          const Type& _Val
       );

    功能

    将一个指定的值从指定的区间中[first,last)“删除”,这里的“删除”是指:把区间内”指定值”的位置腾出,用copy的方式把后面”非指定值”逐一的往前移动。
    比如:
    序列(1234)remove 2后,返回的序列是 1344(3被复制到2的位置,4被复制到3的位置)。

    原理

    第一层算法:

    template<class _FwdIt, class _Ty> inline
    _FwdIt remove(_FwdIt _First, _FwdIt _Last, const _Ty& _Val)
    {   
        // remove each matching _Val
        _First = find(_First, _Last, _Val);
        if (_First == _Last)
        {
            return (_First);// empty sequence, all done
        }
        else
        {   
            // nonempty sequence, worth doing
            _FwdIt _First1 = _First;
            return (_STDEXT unchecked_remove_copy(++_First1,
             _Last, _First, _Val));
        }
    }

    最底层算法:

    /******************************************************
    **_First:第一个待删除值的下一个位置
    **_Last:指向目标容器最后一个元素的下一个位置
    ** _Val:待删除的值
    **_Dest:返回值,初始值为目标容器的第一个指定位置
    *********************************************************/
    template<class _InIt, class _OutIt, class _Ty> inline
    _OutIt _Remove_copy(_InIt _First, _InIt _Last, _OutIt _Dest, 
                        const _Ty& _Val, _Range_checked_iterator_tag)
    {   
        //copy omitting each matching _Val
        for (; _First != _Last; ++_First)
        {
            if (!(*_First == _Val))
            {
                *_Dest++ = *_First;
            }   
        }
    
        return (_Dest);
    }

    特点

    remove算法是稳定的,因为其他元素的相对位置并没有改变。同时remove算法并不能直接的删除特定元素,因此目标的容器大小不变

    算法应用

    源码

    #include "stdafx.h"
    #include <string.h>
    #include <algorithm>
    #include <vector>
    #include <deque>
    #include <functional>
    #include <iostream>
    #include <list>
    #include <iterator>
    
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    
        vector<int> vecContainer;
        const int nLoop = 5;
    
        for (int i = 0; i < nLoop; ++i)
        {
            vecContainer.push_back(i);
        }
    
        vecContainer.insert(vecContainer.end(), 2);
        vecContainer.insert(vecContainer.end(), 5);
        vecContainer.insert(vecContainer.end(), 6);
    
        //0 1 2 3 4 2 5 6 
        vector<int> vecData(vecContainer);
    
        cout <<"before remove:"<<endl;
        copy(vecContainer.begin(), vecContainer.end(), 
             ostream_iterator<int>(cout," "));
        cout << endl;
    
        cout <<"after remove:"<<endl;
        remove(vecContainer.begin(), vecContainer.end(), 2);
        copy(vecContainer.begin(), vecContainer.end(), 
             ostream_iterator<int>(cout," "));
        cout << endl;
    
        //需要使用备份后的vecData
        cout <<"after erase:"<<endl;
        //推荐用法
        vecData.erase(remove(vecData.begin(),vecData.end(), 2), 
                      vecData.end());
        copy(vecData.begin(), vecData.end(),
             ostream_iterator<int>(cout," "));
        cout<<endl;
    
        return 0;
    }
    

    内存变化过程

    这里写图片描述

    运行结果

    这里写图片描述

    结论:使用remove删除成员后需要立即调用erase,确保真正的删除!

  • 相关阅读:
    go调查内存泄漏
    c++ 使用模板按类型统计stl多维容器中元素的数量
    phxpaxos遇到反复拉取checkpoint但是反复失败的问题,给其它节点造成压力
    phxpaxos实现状态机CAS操作
    使用phxpaxos开发过程中遇到的坑
    std::condition_variable::wait_until segment
    c++ protected 访问限定
    c++多态
    IO多路复用的水平触发与边缘触发
    Redis 源码分析系列1-main函数相关调用分析
  • 原文地址:https://www.cnblogs.com/jinxiang1224/p/8468434.html
Copyright © 2011-2022 走看看