您的位置:首页 > 编程语言 > C语言/C++

c++ vector遍历删除元素 出错的问题

2012-03-14 15:16 495 查看
使用iterator 遍历时,删除其中一个出了问题,结果是删除了一个以后 不能再用自增了


c++ vector遍历删除元素

一直对vector的删除操作不太熟悉,现整理下。其中前三部分先补充一些相关知识,然后第四部分给出示例代码。

一、关于Vector的earse方法

iterator erase ( iterator position );
iterator erase ( iterator first, iterator last );


Erase elements
Removes from the vector container either a single element (position) or a range of elements ([first,last) ).

This effectively reduces the vector size by the number of elements removed, calling each element's destructor before.

Because vectors keep an array format, erasing on positions other than the vector end also moves all the elements after the segment erased to their new positions, which may
not be a method as efficient as erasing in other kinds of sequence containers (deque, list).

This invalidates all iterator and references to elements after position or first.


Parameters

All parameters are of member type iterator, which in vector containers are defined as a random access iterator type.

position
Iterator pointing to a single element to be removed from the vector.
first, last
Iterators specifying a range within the vector to be removed: [first,last). i.e., the range includes all the elements between first and last,
including the element pointed by first but not the one pointed by last.


Return value

A random access iterator pointing to the new location of the element that followed the last element erased by the function call, which is the vector end if
the operation erased the last element in the sequence.

=======================================我是勤劳的分割线=========================================

二、关于remove_if ( <algorithm>)

ForwardIterator remove_if ( ForwardIterator first, ForwardIterator last,

Predicate pred );

Remove elements from range
Removes from the range [first,last) the elements for which pred applied to its value is true, and returns an iterator to the new
end of the range, which now includes only the values for which pred was false.

The behavior of this function template is equivalent to:

1

2

3

4

5

6

7

8

9

template < class ForwardIterator, class Predicate >
ForwardIterator remove_if ( ForwardIterator first, ForwardIterator last,
Predicate pred )
{
ForwardIterator result = first;
for ( ; first != last; ++first)
if (!pred(*first)) *result++ = *first;
return result;
}

Notice that this function does not alter the elements past the new end, which keep their old values and are still accessible.


Return value

A forward iterator pointing to the new end of the sequence, which now includes all the elements for which pred was false.

=======================================我是勤劳的分割线=========================================

三、关于find()函数

function template

<algorithm>


template <class InputIterator, class T>
InputIterator find ( InputIterator first, InputIterator last, const T& value );


Find value in range

Returns an iterator to the first element in the range [first,last) that compares equal to value,
or last if not found.

The behavior of this function template is equivalent to:

1

2

3

4

5

6

template<class InputIterator, class T>
InputIterator find ( InputIterator first, InputIterator last, const T& value )
{
for ( ;first!=last; first++) if ( *first==value ) break;
return first;
}

Return Vaule: An iterator to the first element in the range that matches value.

If no element matches, the function returns last.

=======================================我是勤劳的分割线=========================================

四、 下面以代码来演示vector的删除元素的方法,其中用到三个宏DEMO1, DEMO2, DEMO3的目的是使得一个文件能一次多演示几个例子。演示不同的DEMO时,只要在编译时加入 -D 宏名字 即可。如要演示DEMO2时,按如下方法编译:

g++ VectorDelete.cpp -o vec -D DEMO2

C++语言: c++ vector的删除操作

001 /*

002 DATE: 2010.6.25

003 内容:关于vector的遍历删除

004 任何改变 vector 长度的操作都会使已存在的迭代器失效。例如,在调用 push_back 之后,就不能再信赖指向 vector 的迭代器的值了。

005 一个原则:对vector只要做了删除或是增加动作,就要示迭代器已经无效,必须重新从vector对象获取新的迭代器的值,而不能用临时变量、后缀自增等方法

006 */

007 #include <iostream>

008 #include <vector>

009 #include <string>

010 #include <cstring>

011 #include <list>

012 #include <algorithm> //to use remove_if

013 using namespace std;

014

015

016 typedef vector<int> V;

017 typedef vector<int>::iterator VIT;

018 typedef list<int> L;

019 typedef list<int>::iterator LIT;

020 V v;

021 L lis;

022

023

024 class InList

025 {

026 public:

027 InList(list<int> &lis):li(lis){}

028

029 bool operator()(int n)

030 {

031 return find(li.begin(), li.end(), n)!=li.end();

032 }

033 private:

034 list<int> &li;

035 };

036

037

038 int main()

039 {

040 for(int i=0; i<10; ++i) //
初始化v: 0 1 2 3 4 5 6 7 8 9

041 v.push_back(i);

042 for(int i=0; i<5; ++i) //
初始化lis:0 1 2 3 4

043 lis.push_back(i);

044

045 VIT it;

046 //cout<<endl<<v.end()-v.begin()<<endl; //vector容器的iterator是支持加减操作的,这在其他类型的迭代器中很少见

047

048 #ifdef DEMO1

049 //遍历删除v中不等于3的元素的正确方法

050 for(it=v.begin(); it!=v.end();)

051 {

052 if(*it != 3)

053 {

054 //将it赋值为erase()的返回值,它指向the new location of the element that followed the last element erased

055 it = v.erase(it);

056 }

057 else

058 ++it;

059 }

060 for(it=v.begin(); it!=v.end(); ++it)

061 cout<<*it<<endl;

062 #endif

063

064 #ifdef DEMO2

065 //DEMO2的功能: 在v中,删除那些在v和在lis中同时存在的元素,不使用remove_if

066 it = v.begin();

067 VIT del = it;

068 for(; it!=v.end(); ++it)

069 {

070 if(find(lis.begin(),lis.end(),*it) == lis.end())

071 {

072 *del++ = *it;

073 }

074 }//此时,del指向A iterator pointing to the new end of the sequence,which now includes all the elements which is not in lis.

075 //整个v变为 5 6 7 8 9 5 6 7 8 9,其中,del指向第二个5

076 v.erase(del, v.end());

077 for(it=v.begin(); it!=v.end(); ++it)

078 cout<<*it<<endl;

079 #endif

080

081 #ifdef DEMO3

082 //DEMO2的功能: 在v中,删除那些在v和在lis中同时存在的元素,使用remove_if

083

084 /*

085 //如果先单独运行remove_if,则v会变为5 6 7 8 9 5 6 7 8 9

086 //即其前五个值由0 1 2 3 4 变为5 6 7 8 9,这与remove_if的实现有关

087 remove_if(v.begin(), v.end(), InList(lis));

088 for(it=v.begin(); it!=v.end(); ++it)

089 cout<<*it<<endl;

090 */

091

092 //remove_if的返回值是A forward iterator pointing to the new end of the sequence,

093 //which now includes all the elements for which InList(lis) was false.

094 v.erase(remove_if(v.begin(), v.end(), InList(lis)), v.end());

095 for(it=v.begin(); it!=v.end(); ++it) //此时v变为5
6 7 8 9, 0 1 2 3 4被删除

096 cout<<*it<<endl;

097 #endif

098

099 return 0;

100 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: