一個容器就是一些特定型別物件的集合
順序容器的資料結構
array:
如下圖所示 陣列是一個大小固定的資料結構,支援高效的隨機訪問,時間複雜度為O(1),但是插入與刪除等操作比較低效,時間複雜度為O(n),需要做大量的資料搬移工作。因此該容器支援快速隨機訪問,不支援新增或刪除元素。
forward_list:
下圖為一個單連結串列,與陣列相反,它並不需要一塊連續的記憶體空間,它通過“指標”將一組零散的記憶體塊串聯起來使用,連結串列的特點為隨機訪問複雜度高,時間複雜度為O(n),但是插入與刪除操作比較高效,時間複雜度為O(1)。
因此只支援單向順序訪問,在連結串列任何位置進行插入刪除操作都很快。
list:
下圖為一個雙向連結串列,與單向連結串列類似,只是在每個節點多了一個前驅指標,所以該連結串列支援雙向遍歷。
因此該容器支援雙向順序訪問,在連結串列任何位置進行插入刪除操作都很快。
deque:
下圖為單向佇列的資料結構,佇列跟棧一樣,也是一種抽象的資料結構。它具有先進先出的特性,支援在隊尾插入元素,在隊頭刪除元素。deque為雙向佇列的順序容器,顧名思義,雙向佇列的不同之處在於隊頭也是隊尾,隊尾也是隊頭。
因此deque這種容器支援快速隨機訪問,在頭尾位置插入/刪除速度很快。
vector:
vector其實也是一個陣列結構,只不過經過對陣列記憶體空間的管理,使得vector成為了一個動態的陣列結構。
因此vector為可變大小陣列,支援快速隨機訪問,在尾部之外的位置插入或刪除元素可能很慢。
string:
與vector類似的容器,但專門用來儲存字元。隨機訪問快。在尾部插入刪除速度快。
容器選擇原則
-
除非有很好的理由使用其他容器,否則應使用vector。
-
如果程式有很多小元素,且空間額外開銷很重要,則不要使用連結串列。因為連結串列每個節點都會至少有一個後繼指標,因此會佔用很多額外空間。
-
如果程式要求隨機訪問元素,則使用陣列(vector)或佇列(deque)。string也支援隨機訪問,但是該容器專門用於儲存字元,array則是因為該陣列為固定大小陣列。
-
如果程式要求在容器的中間插入或刪除元素,應使用連結串列。
-
如果程式要求在容器的頭尾插入或刪除元素,但不在中間插入,則使用佇列。
-
如果程式要求只有在讀取輸入時需要在容器中插入元素,隨後需要隨機訪問元素,則
-
首先確定真的需要中間插入元素,當處理輸入資料時,通常可以很容易的在vector容器末追加資料,再呼叫標準庫中的sort函式來對容器中的元素進行重排,以避免中間插入操作
-
如果必須在中間位置插入元素,則在輸入階段考慮list,一旦輸入完成,將list中的資料拷貝到另一個vector中。
-
容器操作
建構函式 | |
---|---|
C c; | 預設建構函式,構造空容器(array) |
C c1(c2); | 構造 c2 的拷貝 c1 |
C c(b,e); | 構造 c ,將迭代器 b 和 e指定的範圍內的元素拷貝到c |
C c{a,b,c,...} |
賦值與swap | |
---|---|
c1=c2; | 將 c1 中的元素替換為 c2 中的元素 |
c1=(a,b,c...); | 將 c1 中的元素替換為列表中元素(除array) |
a.swap(b); | 交換 a 和 b 的元素,swap通常比c2從c1拷貝元素快得多 |
swap(a,b); | 與 a.swap 等價 |
assign操作 | 不適用於關聯容器和array |
seq.assign(b,e); | 將 seq 中的元素替換為迭代器 b 和 e 所表示的範圍中的元素。迭代器 b 和 e 不能指向seq中的元素 |
seq.assign(i1); | 將seq中的元素替換為初始化列表 i1 中的元素 |
seq.assign(n,t); | 將 seq 中的元素替換為 n 個值為 t 的元素 |
大小 | |
---|---|
c.size(); | c中元素的數目(不支援forward_list) |
c.max_size(); | c可儲存的最大元素數目 |
c.empty(); | 若c中儲存了元素,返回 false,否則返回 true |