STL與泛型編程 第三周 博覽網

deque

  • deque其實是分段連續,即在其內部并不是連續分布的。但抽象為連續的分布。如下圖:
    image.png

    image.png

    deque可以前后擴充。其中map可以認為是一個控制中心,它其實是一個vector,當map容量不夠時進行擴充,擴充后會進行數據copy,但是它會將數據copy到中間位置。
  • deque模擬連續空間由deque iterator完成,
  • array、vector、deque均抽象為連續空間可以使用+=、-=、[]運算符。其他容器則不可以。
  • stack、queue使用的是deque,只不過取消掉一部分功能。stack、queue其實就是一個adapter,它們都不允許遍歷,也不提供iterator。stack、queue都可以選擇list或者deque作為底層結構,但是deque為默認底層結構,速度更快一點。stack可以選擇vector作為底部支撐,但是queue不可以選擇vector作為底層結構。


    image.png

    image.png
  • stack、queue默認基于deque實現,priority_queue是在vector上實現的。priority_queue還要求隨機訪問能力,故它只能構造在vector和deque之上,不能基于list構造。
  • stack包含在stack頭文件中,queue和priority_queue均在queue頭文件中。

各容器特殊操作

  • array不支持C c(b,e)操作,即構造C,將迭代器b和e指定的范圍內的元素拷貝到C
  • vector deque array支持迭代器+=操作。其他均不支持。包括list。
  • list不支持迭代器的比較運算符(除了== !=)
  • forward_list因為無法保證size運算的常數復雜度,所以不支持size()運算.
  • 所有容器都支持== !=操作,但只有順序容器支持< <= > >=操作。比較兩個容器其實就是將元素逐對進行比較。
  • 只有順序容器可以(不包括array)的構造函數才能接收容器大小的參數。例如:
    list<string> a(4,"haha");
    array<int,4> c;//array在創建時必須指定大小
  • 只有vector,array,deque,string提供快速隨機訪問容器。使用at()成員函數可以檢查是否越界,如果下表越界會拋出out_of_range異常。
  • 訪問容器前必須檢查是否未空,否則出現知名錯誤。
  • 除了array外,swap()成員函數不對任何元素進行拷貝、刪除和插入操作,它不會移動元素本省,它只是改變容器內部的數據結構,因此可以保證在常數時間內完成,因此swap后指向元素的迭代器、引用和指針仍指向這個元素。
  • swap 兩個array會真正交換它們的元素。因此指向元素的迭代器、引用和指針指向array的相同位置,但是元素值已經不同了。
  • swap有成員函數版本和非成員函數版本,統一使用非成員函數版本是一個好習慣。
  • 賦值相關預算會導致指向左邊容器內部的迭代器,引用和指針失效。
  • 對vector、string、deque插入元素(array不支持此操作)會使指向容器的迭代器、引用和指針失效。導致無法再使用,使用時可以使用insert()返回的值對其重新進行賦值。
  • 刪除deque中除首尾元素之外的任何元素都會使所有迭代器、引用和指針失效。指向vector或string中刪除點后位置的迭代器、引用和指針都會失效。
  • 對于vector、deuqe、list的insert(p)會返回指向新添加元素的第一個元素,插入位置為迭代器p指向元素的前面;erase(p)會刪除p指向的元素,返回一個被刪除元素之后元素的迭代器。
  • 對于forward_list由于其特殊性,insert_after(p)為在p之后插入元素,返回一個指向最后一個元素的迭代器;erase_after(p)為刪除p指向的位置之后的元素,返回一個被刪除元素之后元素的迭代器。
  • 由于向迭代器添加元素和刪除元素的代碼可能會使失效,因此必須保證每次改變容器的操作之后都正確地定位迭代器。這個建議對于vector、string、和deque尤為重要。
  • 當我們添加/刪除vector或string的元素后,或者在deque中首元素外任何位置添加/刪除元素后,原來end返回的尾后迭代器均失效,因此不要輕易保存尾后迭代器進行循環判斷,而是在每次循環后都進行更新,end()的運行速度一般很快。

string

  • 對于string還有特殊版本的insert和earse漢本,它接收的第一個參數是下表,而不是迭代器。

associative container - rb_tree

  • associative container包括map、set、multiset、multimap其底層支持就是一個RB_Tree.
  • 紅黑樹是一種平衡二叉搜索樹。這種結構有利于search和insert。我們不應使用RB_Tree的iterator改變元素的值,因為元素在rb_Tree中的序列是嚴格排列規則的。rb_tree提供兩種insertion操作:inser_unique()和insert_equal(),地址一種表示節點key在樹中獨一無二,重復的key無法放入樹中,后者表示節點可以重復,重復的key可以被放入樹中。
    image.png
  • set/multiset提供遍歷操作及iterator。無法使用iterator改變key值。
  • map/multimap提供遍歷操作及iterator。通過iterator無法改變map和multimap的key值,但是可以改變它的data值。
  • map的operator[]有特殊的功能,可以通過它來方元素進去。multimap則無此功能。

unorder container - hashtable

  • unorder_map/multimap unorder_set/multitset底層結構均為容器hashtable。
  • hashtable的工作原理


    image.png

    如果元素個數超過buckets內的個數時,則buckets進行擴充,變為原來的2倍數字附近的質數的個數。在gun2.9中內置的hashtable中buckets的大小,初始為53,第一次擴大為97,第三次擴大為193,以此類推。每一次buckets的擴充都消耗大量時間,包括vector的增長以及元素的重新分配。

  • hashtable類沒有為std:: string提供默認的hashfunction,所以要自己寫一個hashfunction來處理字符串產生hashcode。但是為C風格的字符串提供了默認的產生的hashcode的hashfunction。
  • 我們通常不對關聯容器使用泛型算法。關聯容器可以使用只讀取元素的算法,一般不使用泛型find算法,而使用關聯容器專門的find算法。
  • 關聯容器的關鍵字類型要嘛自己有定義的<操作符,要嘛在實例化泛型時傳入一個函數指針來提供比較運算。
bool compareIsbn(const Book &lhs,const Book &rhs) {...}//Book是一個類
set<Book,decltype(compareIsbn)*> bookstore(compareIsbn);//創建實例時傳入一個比較函數
//或者如下
typedef bool (*pf) (const Book &,const Book &);
set<Book,pf> bookstore(compareIsbn)
  • 對于set或者map,insert(或emplace)返回一個pair類型,first是一個迭代器,指向給定關鍵字元素,second為一個bool值,指示是否插入成功。
  • 對于允許重復關鍵字的容器,insert或者emplace只返回一個指向插入元素的迭代器。
  • 對于map進行下表運算符操作時,如果元素不在map中,則會添加元素到map中,因此如果只是向知道一個元素是否已在map中,但不存在時不想添加元素時不可以使用下表運算符
  • 對于無序關聯容器,不需要提供<運算符,只需要提供==運算符即可。
  • 默認情況下,無序容器使用關鍵字類型的==運算符來比較元素,它們還使用一個hash<key_type>類型的對象來生成每個元素的哈希值;標準庫為內置類型(包括指針)、string和只能指針類型定義了hash,因此我們可以直接定義關鍵字是內置以上類型的無序容器;但是我們不能直接定義關鍵字類型為自定義類類型的無序容器,必須提供自己的hash模板版本。自定義類型版本
unorderde_multiset<Book,decltype(hasher)*,decltype(eqOp)* > bookstore(42,hasher,eqOp);
/*hasher,eqOp為函數名,初始化對象傳入的參數分別為同大小、哈希函數指針、相等行判斷運算符指針*/
unordered_set <Foo,decltype(FooHash)* >fooSet(10,FooHash);
/*如果在FOO類中定義了==運算符,則可以只重載哈希函數*/
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容