順序容器初探(上)

JoJo_bai發表於2021-03-17

一個容器就是一些特定型別物件的集合

順序容器的資料結構

array:

如下圖所示 陣列是一個大小固定的資料結構,支援高效的隨機訪問,時間複雜度為O(1),但是插入與刪除等操作比較低效,時間複雜度為O(n),需要做大量的資料搬移工作。因此該容器支援快速隨機訪問,不支援新增或刪除元素。

forward_list:

下圖為一個單連結串列,與陣列相反,它並不需要一塊連續的記憶體空間,它通過“指標”將一組零散的記憶體塊串聯起來使用,連結串列的特點為隨機訪問複雜度高,時間複雜度為O(n),但是插入與刪除操作比較高效,時間複雜度為O(1)。

因此只支援單向順序訪問,在連結串列任何位置進行插入刪除操作都很快。

 

 

 

 

list:

下圖為一個雙向連結串列,與單向連結串列類似,只是在每個節點多了一個前驅指標,所以該連結串列支援雙向遍歷。

因此該容器支援雙向順序訪問,在連結串列任何位置進行插入刪除操作都很快。

 

deque:

下圖為單向佇列的資料結構,佇列跟棧一樣,也是一種抽象的資料結構。它具有先進先出的特性,支援在隊尾插入元素,在隊頭刪除元素。deque為雙向佇列的順序容器,顧名思義,雙向佇列的不同之處在於隊頭也是隊尾,隊尾也是隊頭。

因此deque這種容器支援快速隨機訪問,在頭尾位置插入/刪除速度很快。

 

vector:

vector其實也是一個陣列結構,只不過經過對陣列記憶體空間的管理,使得vector成為了一個動態的陣列結構。

因此vector為可變大小陣列,支援快速隨機訪問,在尾部之外的位置插入或刪除元素可能很慢。

string:

與vector類似的容器,但專門用來儲存字元。隨機訪問快。在尾部插入刪除速度快。

容器選擇原則

  1. 除非有很好的理由使用其他容器,否則應使用vector。

  2. 如果程式有很多小元素,且空間額外開銷很重要,則不要使用連結串列。因為連結串列每個節點都會至少有一個後繼指標,因此會佔用很多額外空間。

  3. 如果程式要求隨機訪問元素,則使用陣列(vector)或佇列(deque)。string也支援隨機訪問,但是該容器專門用於儲存字元,array則是因為該陣列為固定大小陣列。

  4. 如果程式要求在容器的中間插入或刪除元素,應使用連結串列。

  5. 如果程式要求在容器的頭尾插入或刪除元素,但不在中間插入,則使用佇列。

  6. 如果程式要求只有在讀取輸入時需要在容器中插入元素,隨後需要隨機訪問元素,則

    • 首先確定真的需要中間插入元素,當處理輸入資料時,通常可以很容易的在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,...} 列表初始化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

 

 

相關文章