STL中謹慎選擇刪除元素的方法,stl謹慎選擇
一、要刪除容器中有特定值的所有對象
1、如果容器是vector、string或deque,則使用erase-remove習慣用法。例如:
vector<int> c;
c.erase(remove(c.begin(),c.end(),1963),c.end());//刪除值是1963的元素
下面講一下演算法remove:
template<classForwardIterator,class T>
ForwardIteratorremove(ForwardIterator first,ForwardIterator last,const T& value)
{
first = find(first,last,value);
ForwardIterator next = first;
return first ==last?first:remove_copy(++next,last,first,value);
}
template<classInputIterator,class OutputIterator,class T>
OutputIteratorremove_copy(InputIterator first,InputIterator last,OutputIterator result,constT& value)
{
for(;first != last;++first)
if (*first != value)
{
*result = *first;
++result;
}
return result;
}
移除[first,last)之中所有與value相等的元素。這一演算法並不真正從容器中刪除那些元素(換句話說容器大小並為改變),而是將每一個不與value相等(也就是我們並不打算移除)的元素輪番賦值給first之後的空間。返回值標示出重新整理後的最後元素的下一位置。例如序列{0,1,0,2,0,3,0,4},如果我們執行remove(),希望移除所有0值元素,執行結果將是{1,2,3,4,0,3,0,4}。每一個與0不相等的元素,1,2,3,4,分別被拷貝到第一、二、三、四個位置上。第四個位置以後不動,換句話說是第四個位置之後是這一演算法留下的殘餘資料。返回值ForwardIterator指向第五個位置。如果要刪除那些殘餘資料,可將返回的迭代器交給區間所在之容器的erase()成員函數。注意,array不適合使用remove()和remove_if(),因為array無法縮小尺寸,導致殘餘資料永遠存在。對array而言,較受歡迎的演算法是remove_copy()和remove_copy_if()。
remove_copy移除[first,last)區間內所有與value相等的元素。它並不真正從容器中刪除那些元素,而是將結果複製到一個以result標示起始位置的容器身上。新容器可以和原容器重疊,但如果對新容器實際給值時,超越了舊容器的大小,會產生無法預期的結果。返回值OutputIterator指出被複製的最後元素的下一位置。
2、如果容器是list,則使用list::remove。例如:
list<int> c;
c.remove(1963);//該成員函數無返回值
3、如果容器是一個標準關聯容器,則使用它的erase成員函數。例如:
map<int,int>c;
c.erase(1963);//刪除鍵值是1963的元素
對於標準關聯容器使用任何名為remove的操作都是完全錯誤的。這樣的容器沒有名為remove的成員函數,使用remove演算法可能會覆蓋容器的值,同時可能會破壞容器。
二、要刪除容器中滿足特定判別式(條件)的所有對象
1、如果容器是vector、string或deque,則使用erase-remove_if習慣用法。例如我們不再從c中刪除所有等於特定值的元素,而是刪除使下面的判別式返回true的每一個對象:
bool badvalue(int);
c.erase(remove_if(c.begin(),c.end(),badvalue),c.end());
2、對於list,則使用list::remove_if。例如:
c.remove_if(badvalue);
3、如果容器是一個標準關聯容器,則使用remove_copy_if和swap,或者寫一個迴圈來遍曆容器中的元素,記住當把迭代器傳給erase時,要對它進行尾碼遞增。例如:
AssocContainer<int>c;
…
AssocContainer<int>goodvalues;
Remove_copy_if(c.begin(),c.end(),inserter(goodvalues,goodvalues.end()),badvalue);
c.swap(goodvalues);
或者
AssocContainer<int>c;
…
for(AssocContainer<int>::iteratori = c.begin();i != c.end();)
{
if(badvalue(*i))
c.erase(i++);
else
++i;
}
三、要在迴圈內部做某些(除了刪除對象之外的)操作:
1、如果容器是一個標準序列容器,則寫一個迴圈來遍曆容器中的元素,記住每次調用erase時,要用它的返回值更新迭代器。例如:
ofstream logFile;
SeqContainer<int>c;
for (SeqContainer<int>::iteratori = c.begin();i != c.end();)
{
if (badvalue(*i))
{
logFile << “Erasing” << *i<< ‘\n’;
i = c.erase(i);//把erase的返回值賦給i,使i的值保持有效
}
else
{
++i;
}
}
2、如果容器是一個標準關聯容器,則寫一個迴圈來遍曆容器中的元素,記住當把迭代器傳給erase時,要對迭代器做尾碼遞增。例如:
ofstream logFile;
AssocContainer<int>c;
…
for(AssocContainer<int>::iterator i = c.begin();i != c.end();)
{
if (badvalue(*i))
{
logFile<< “Erasing ” << *i << ‘\n’;
c.erase(i++);
}
else
++i;
}
c++ stl中堆操作怎刪除元素
只能重建堆。堆的特性就是這樣,只能在堆頂操作。
如果你真的需要時常在中間刪掉元素,你根本不應該選擇使用堆。
C++中STL各種移除元素方法
容器c
當c是vector、string、或deque時,用
c.erase( remove( c.begin(), c.end(), 1963 ), c.end() );//移除c中值是1963的元素
當c是list時,用
c.remove(1963);
當c是關聯容器時,用
c.erase(1963);