STL容器及算法題:刪除奇數的QQ號

最近思考到這樣一個題目:在STL的set和vector容器裏存儲了1億個QQ號,編寫函數刪除奇數QQ號。git

1. STL容器簡介

首先了解一下 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 優先隊列,一個隊列,其中元素的次序是由做用於所存儲值對上的某種謂詞決定的,擁有高優先級的元素會先被出隊。

2. 算法解析

第一個思路就是使用erase函數一個個去刪,(不知道有沒有什麼更好的方法請在評論裏指點一下,謝謝)這裏,set和vector的存儲方式是不同的。可是它們都提供了一個刪除元素的接口erase數組

// set
iterator    erase(iterator it);
iterator    erase(iterator first, iterator last);
size_type   erase( const Key& key);
  • 第一個成員函數:刪除 set 中由迭代器 it 指向的元素;
  • 第二個成員函數:刪除 set 中區間爲 [first , last )中的全部元素;
  • 第一和第二個成員函數都返回一個迭代器,指向緊接着被刪除元素的下一個元素,若是沒有這樣的元素,則迭代器指向 end()。
  • 第三個成員函數:刪除 set 中區間爲 [lower_bound(key) , upper_bound(key) )中的具備給定排序鍵key的全部元素,返回刪除元素的個數
// vector , list ,  deque
iterator    erase(iterator it);
iterator    erase(iterator first, iterator last);
  • 第一個成員函數:刪除 vector/list/deque 中由迭代器 it 指向的元素;
  • 第二個成員函數:刪除 vector/list/deque 中區間爲 [first , last )中的全部元素;
  • 第一和第二個成員函數都返回一個迭代器,指向緊接着被刪除元素的下一個元素,若是沒有這樣的元素,則迭代器指向 end()。
  • vector時,刪除 N 個元素將致使調用 N 次析構函數以及從刪除點至序列末端的每一個元素都被賦值一次。因爲不須要進行存儲空間的從新分配,因此只有從指向第一個被刪除元素到序列末端這個區域的迭代器以及引用纔會失效。
  • list時,刪除N個元素將調用N次析構函數。因爲沒有進行任何從新分配發生,只有指向被刪除對象的迭代器和引用纔會變爲無效。
  • deque時,刪除N個元素將致使N次調用析構函數以及從刪除點至序列較近的末端的每一個元素都被賦值一次。在序列的兩端刪除一個元素僅使得原先指向被刪除元素的迭代器和引用變得無效,不然,刪除一個元素將致使全部的迭代器和引用都變的無效。

瞭解了這個之後,能發現,算法題中的說存儲在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

完整測試源碼對象

附錄

相關文章
相關標籤/搜索