1.引言
以下代碼有什么問題,如何修改?
#include#includeusing namespace std;void print(vector);//傳引用不妥??!int main(){ vector array; array.push_back(1); array.push_back(6); array.push_back(6); array.push_back(3);//刪除array中的所有的6 vector::iterator itor; vector::iterator itor2; itor=array.begin(); for (itor=array.begin();itor!=array.end();itor++;) { if (6==*itor) { itor2=itor; array.erase(itor2); } } print(array); return 0;}void print(vector v){ cout<'\nvector size="" is:="">'\nvector><><>
2.vector中erase源碼
這段代碼運(yùn)行后容量只減小1,具體問題出在哪不知道。先看一下erase的源碼。
iterator erase(iterator position) { if (position + 1 != end()) //若position不是指向最后一個(gè)元素 copy(position + 1, finish, position); //運(yùn)用的是copy,將刪除位置的元素向后移動(dòng) --finish;//vector中finish所指位置為end()返回值 destroy(finish); return position;}iterator erase(iterator first, iterator last) //允許last在first之前,后果自負(fù){ iterator i = copy(last, finish, first);destroy(i, finish);finish = finish - (last - first); return first;}
現(xiàn)在知道了,如果這時(shí)刪除一個(gè)元素之后,itor已經(jīng)指向下一個(gè)元素,所以再調(diào)用itor++,那么連續(xù)的2個(gè)6就只能刪除前一個(gè)。
所以以上的for循環(huán)可以改為:
for (itor=array.begin();itor!=array.end();itor++;){ if (6==*itor) { itor2=itor; array.erase(itor2); itor--; }}
3.remove源碼
但是這樣的代碼可讀性欠佳,還有一種改法就是更加規(guī)范的簡潔的操作:調(diào)用算法remove,之后再進(jìn)行erase。
此時(shí)將for循環(huán)替代為:array.erase(remove(array.begin().array.end(),6),array.end());當(dāng)然這個(gè)時(shí)候要包含頭文件。
為什么要?jiǎng)h除,remove返回后的迭代器到vector末尾的元素呢?看remove算法源碼。
remove操作移除[first,last)之中所有與value相等的元素。這一算法并不真正從容器中刪除那些元素(換句話說容器的大小并沒有改變),而是將每一個(gè)不與value相等的元素輪番賦值給first之后的空間。返回值ForwardIterator標(biāo)示出重新整理后的最后元素的下一個(gè)位置。例如序列{0,1,0,2,0,3,0,4},如果執(zhí)行remove刪除0,則結(jié)果是{1,2,3,4,0,3,0,4},返回值ForwardIterator指向第5個(gè)元素。所以如果要?jiǎng)h除那些殘余元素可以使用erase的兩迭代器版本。源碼如下:
tamplateForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value){ first=find(first, last, value);//找到第一個(gè)相等的元素 ForwardIterator next = first;//以next標(biāo)示出來 //以下利用“remove_copy()允許新舊容器重疊”的性質(zhì),進(jìn)行移除操作 //并將結(jié)果置于原容器中 return first == last ? first : remove_copy(++next,last,first,value);}
remove_copy并不改變?cè)瓉淼娜萜?,只是將所要?jiǎng)h除的值刪除后,將新容器存儲(chǔ)在result迭代器所指的位置處。
tamplateOutputIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value){ for(;first != last;++first) if(*first != value) //如果不相等 { *result = *first; //賦值給新容器 ++result; } return result;}
當(dāng)然remove函數(shù)也有仿函數(shù)版本的remove_if,remove_copy_if。
4.list中的remove和erase操作
list中的erase:
iterator erase(iterator position){ link_type next_node = link_typr(position.node->next); link_type prev_node = link_typr(position.node->prev); prev_node->next = next_node; next_node->prev = prev_node; destroy_node(position.node); return iterator(next_node);}
remove是算法庫中的一個(gè)算法,但是list的結(jié)構(gòu)使用這種remove算法時(shí)效率低下。根據(jù)list的結(jié)構(gòu),標(biāo)準(zhǔn)庫專門為list設(shè)計(jì)了remove操作(其他容器是沒有的)。
templatevoid list::remove(const T& value){ iterator first = begin(); iterator last = end(); while(first != last) { iterator next = first; ++next; if(*first == value) erase(first); first = next; }}
5.deque、set、map的erase操作
待補(bǔ)充…………………..