STL容器的遍历插入或删除(迭代器失效问题的统一解决)

来源:互联网 发布:jsp管理系统源码 编辑:程序博客网 时间:2024/06/13 02:12

STL容器根据迭代器的失效问题,其实可以分为两类容器:

(1)数组型容器的插入删除操作:vector、string、deque(均为顺序存储)
        由于这类容器的插入或删除都会使所有迭代器失效,因此每次插入删除后都需要重新定位

(2)结点型数据容器的插入删除操作:list(使用链表存储)、map(使用红黑树存储)、set(使用红黑树存储)
        由于这类容器删除时只会失效当前迭代器,而插入时不会使任何迭代器失效, 因此插入时不需重新定位,但是删除时需重新定位


一、遍历删除
    
为追求操作统一,两类容器在删除元素时每次都重新定位,即:

每次条件满足需要删除时,获取删除后返回的迭代器,而返回的迭代器直接指向了下一个位置,因此迭代器不用另外自增操作。

对于不满足条件时,需要迭代器另外自增操作,以保证循环正常进行,否则将进入死循环。

    //vector示例第一类容器    vector<string> vec_str={"hello","hi","world"};    auto it=vec_str.begin();    while(it!=vec_str.end()){        if(it->size()==5)//指定位置删除示例            it=vec_str.erase(it);//返回的it自动指向下一个位置        else            it++;//未删除应移到下一个位置,否则陷入死循环    }    for(auto e:vec_str)        cout<<e<<endl;    vec_str.clear();
    //map示例第二类容器    map<int,int> map_values;    for(int i=0;i<5;i++){        map_values.insert(pair<int,int>(i,i));    }    auto iter=map_values.begin();    while(iter!=map_values.end()){        if((iter->first)%2==0){//指定位置删除示例            iter=map_values.erase(iter);//返回的it指向下一个位置        }        else            iter++;    }    for(auto e:map_values){        cout<<e.first<<" "<<e.second<<endl;    }    map_values.clear();

二、遍历插入


首先第二类容器在插入时不会使任何迭代器失效,因此循环插入时不存在问题。
但是第一类容器存在迭代器失效问题,由于vector和list容器的插入操作都是前插,并且返回指向插入后的元素的迭代器,如果每次重新定位到下一个元素,需要向前进两个位置!因此每次重新定位比较麻烦,并且vector插入效率低下,使用list替换vector,避开迭代器失效问题是最佳选择。
注意不要妄想使用insert向map或set的指定位置插入元素,map和set都是有序容器(底层是RBT),因此插入后map会自动按key排序元素,而set会自动排序元素,因此遍历时向指定位置(迭代器位置)插入的需求不会发生在map,如果发生了请考虑重新选择容器。

 //vector示例第一类容器(list作为中间容器示例第二类容器)    vec_str.push_back("hello");    vec_str.push_back("hi");    vec_str.push_back("world");    list<string> list_str;    list_str.resize(vec_str.size());//resize必须,否则copy越界    copy(vec_str.begin(),vec_str.end(),list_str.begin());    for(auto it1=list_str.begin();it1!=list_str.end();it1++){        if(it1->size()==5)            list_str.insert(it1,"test");//直接插入,迭代器不会失效    }    vec_str.resize(list_str.size());//resize必须,list_str大小已变,否则copy越界    copy(list_str.begin(),list_str.end(),vec_str.begin());    for(auto e:vec_str){        cout<<e<<endl;    }

0 0
原创粉丝点击