最近思考到這樣一個題目:在STL的set和vector容器裏存儲了1億個QQ號,編寫函數刪除奇數QQ號。git
首先了解一下 set 和 vector 以及其餘相似的 STL 容器:github
容器 | 描述 |
---|---|
vector | 向量,一個有着N個或更多連續存儲的元素的數組。 |
list | 列表,一個由節點組成的雙向鏈表,每一個節點中包含一個元素。 |
deque | 雙隊列,一個有着N個或更多連續存儲的指向不一樣元素的指針組成的數組。 |
set | 集合,一個由節點組成的紅/黑樹,每一個節點包含一個元素,節點之間以某種做用與元素對的謂詞排序,沒有兩個不一樣的元素可以擁有相同的次序。 |
multiset | 多重集合,容許存在兩個次序相同的元素的集合。 |
map | 映射,一個由{鍵 , 值}對組成的集合,以某種做用於鍵對上的謂詞排序,使用pair<鍵, 值>。 |
multimap | 多重映射,容許鍵有重複的,即一個鍵能夠有多個對應的值。 |
容器 | vector | deque | list | set/map |
---|---|---|---|---|
插入/刪除 | N | N | 常量 | log(N) |
從前面添加 | N | 常量 | 常量 | log(N) |
find(val) | N | N | N | log(N) |
X(N) | 常量 | 常量 | N | N |
指針 | 0 | 1 | 2 | 3 |
這些容器幾乎是由其餘容器實現的容器,只是對存取元素方面進行了部分的限制。算法
容器 | 描述 |
---|---|
stack | 棧,後進先出的隊列。 |
queue | 隊列,先進先出。 |
priority_queue | 優先隊列,一個隊列,其中元素的次序是由做用於所存儲值對上的某種謂詞決定的,擁有高優先級的元素會先被出隊。 |
第一個思路就是使用erase函數一個個去刪,(不知道有沒有什麼更好的方法請在評論裏指點一下,謝謝)這裏,set和vector的存儲方式是不同的。可是它們都提供了一個刪除元素的接口erase:數組
// set iterator erase(iterator it); iterator erase(iterator first, iterator last); size_type erase( const Key& key);
// vector , list , deque iterator erase(iterator it); iterator erase(iterator first, iterator last);
瞭解了這個之後,能發現,算法題中的說存儲在set和vector中,其實其內部存儲是不同的,刪除的實現原理也是不一樣的。但均可以用同一個接口erase()去實現!及時這時候添加說還存儲在list和deque中,也是可使用的。咱們能夠寫兩個函數去實現這個功能,但因爲在兩個容器中,而調用的接口又都是同樣的,因此天然而然想到可使用模板函數!這是其一。微信
第二,題目中說是QQ號,衆所周知,QQ目前已經多達11位了,之後還會更長,因此將QQ號設爲整型確定是不合適的了,因此這裏須要使用long long 。同時,遍歷容器時,確定是要使用迭代器來進行遍歷的,這樣能保證速度。函數
第三,題目中說一億個QQ號,目前還不知道這裏藏着什麼坑,感受是有的,我寫的代碼反正是死掉了,一億條,添加和刪除的循環都搞死了。還請大神幫忙分析分析!測試
因此基於以上分析,寫出如下代碼:指針
#include <utility> #include <set> #include <vector> typedef long long dlong; template <typename T> void qq_delete_stl_template(T &t){ typename T::iterator it=t.begin(); //typename用來講明T::iterator是一個類型, //不然iterator會被認爲是T中的一個成員變量 while(it!=t.end()){ //每次刪除後都會致使t.end()指向的都是不一樣的位置 if((*it)&1){ //奇數 it=t.erase(it); //刪除迭代起指向的內容,並返回刪除後的下一項內容 }else{ ++it; } } } //調用時應該是: set<dlong> s; //假設s裏存有1億個QQ號 qq_delete_stl_template(s); vector<dlong> v; //假設v裏存有1億個QQ號 qq_delete_stl_template(v);
分析的比較淺顯,但願大神指教!code
完整測試源碼對象