STL容器的刪除操做

在應用中,咱們一般不可避免地要對容器中的某些特定元素進行刪除操做。這看起來並非什麼困難的問題。咱們先寫一個循環來迭代容器中的元素,若是迭代元素是要刪除的元素,則刪除之。代碼以下所示:算法

  1. vector<int> intContainer;
  2. for(vector<int>::iterator is = intContainer.begin(); it != intContainer.end(); ++it)
  3. {
  4. if ( *it == 25)
  5. intContainer.erase(it);
  6. }
vector<int> intContainer; for(vector<int>::iterator is = intContainer.begin(); it != intContainer.end(); ++it) { if ( *it == 25) intContainer.erase(it); } 寫出此代碼的原意是將vector中值爲25的元素刪除,但不幸的是,這樣作是錯誤的,這麼作會帶來詭異的未定義行爲。由於當一個容器的一個元素被刪除時,指向那個元素的全部迭代器將失效。當intContainer.erase(it)返回時,it已經失效。在for循環中對於失效的it執行自增操做,這是一件多麼不靠譜的事情啊。

既然這樣行不通,那麼咱們能夠求助於STL提供的remove算法。藉助remove算法來達到刪除元素的目的。函數

  1. vector<int> intContainer;
  2. size_t before_size = intContainer.size();
  3. remove(intContainer.begin(), intContainer.end(), 25);
  4. size_t after_size = intContainer.size();<span style="font-family:'Times New Roman';font-size:18px;">
  5. </span>
vector<int> intContainer; size_t before_size = intContainer.size(); remove(intContainer.begin(), intContainer.end(), 25); size_t after_size = intContainer.size();<span style="font-family:'Times New Roman';font-size:18px;"> </span> 運行程序之後發現before_size和after_size是同樣的,說明元素並無被真正刪除。寫出以上程序,是處於對remove算法的不瞭解而致。STL中remove算法會將不應刪除的元素前移,而後返回一個迭代器,該迭代器指向的是那個應該刪除的元素,僅此而已。因此若是要真正刪除這一元素,在調用remove以後還必須調用erase,這就是STL容器元素刪除的"erase_remove"的慣用法。
  1. vector<int> intContainer;
  2. intContainer.erase( remove(intContainer.begin(), intContainer.end(), 25), intContainer.end());<span style="font-family:'Times New Roman';font-size:18px;">
  3. </span>
vector<int> intContainer; intContainer.erase( remove(intContainer.begin(), intContainer.end(), 25), intContainer.end());<span style="font-family:'Times New Roman';font-size:18px;"> </span>


erase-remove的慣用法適用於連續內存容器,好比vector,deque和string,它也一樣適用於list,可是並非咱們推薦的方法,由於使用list成員函數remove會更高效,代碼以下:spa

  1. list<int> list_int;
  2. ....
  3. list_int.remove(25);
list<int> list_int; .... list_int.remove(25); 若是是關聯容器呢?標準關聯容器沒有remove成員函數,使用STL算法的remove函數時編譯同不過。因此上述remove形式對於標準關聯容器並不適用。在這種狀況下,解決辦法就是調用erase:
  1. map<int, int> mapContainer;
  2. ...
  3. mapContainer.erase(25);
map<int, int> mapContainer; ... mapContainer.erase(25); 對於標準關聯容器,這樣的元素刪除方式是簡單有效的,時間複雜度爲O(logn).

當咱們須要刪除的不是某一個元素,而是具有某一條件的元素的時候,咱們只須要將remove替換成remove_if便可
.net

  1. bool Is2BeRemove(int value)
  2. {
  3. return value < 25;
  4. }
  5. vector<int> nVec;
  6. list<int> nList;
  7. ....
  8. nVec.erase(remove_if(nVec.begin(), nVec.end(), Is2BeRemove), nVec.end());
  9. nList.remove_if(Is2BeRemove);<span style="font-family:'Times New Roman';font-size:18px;">
  10. </span>
bool Is2BeRemove(int value) { return value < 25; } vector<int> nVec; list<int> nList; .... nVec.erase(remove_if(nVec.begin(), nVec.end(), Is2BeRemove), nVec.end()); nList.remove_if(Is2BeRemove);<span style="font-family:'Times New Roman';font-size:18px;"> </span>


總結以下

刪除容器中具備特定值的元素:blog

若是容器是ector、string或者deque,使用erase-remove的慣用法。若是容器是list,使用list::remove。若是容器是標準關聯容器,使用它的erase成員函數。內存

刪除容器中知足某些條件的元素:rem

若是容器是ector、string或者deque,使用erase-remove_if的慣用法。若是容器是list,使用list::remove_if。若是容器是標準關聯容器,使用remove_copy_if & swap 組合算法,或者本身協議個遍歷刪除算法。get

本文轉自:http://blog.csdn.net/lalor/article/details/7642797string

相關文章
相關標籤/搜索