各種容器的特性
vector
典型的序列容器,
c++標準嚴格要求次容器的實現記憶體必須是連續的,唯一可以和標準
c相容的
stl容器,任意元素的讀取、修改具有常數時間複雜度,在序列尾部進行插入、刪除是常數時間複雜度,但在序列的頭部插入、刪除的時間複雜度是
o(n)
,可以在任何位置插入新元素,有隨機訪問功能,插入刪除操作需要考慮。
deque
序列容器,記憶體也是連續的,和
vector
相似,區別在於在序列的頭部插入和刪除操作也是常數時間複雜度
,可以在任何位置插入新元素,有隨機訪問功能。
list
序列容器,記憶體是不連續的,任意元素的訪問、修改時間複雜度是
o(n)
,插入、刪除操作是常數時間複雜度
,可以在任何位置插入新元素。
set關聯容器,元素不允許有重複,資料被組織成一棵紅黑樹,查詢的速度非常快,時間複雜度是
o(logn)
multiset
關聯容器,和
set一樣,卻別是允許有重複的元素,具備時間複雜度
o(logn)
查詢功能。
map關聯容器,按照
方式組成集合,按照鍵組織成一棵紅黑樹,查詢的時間複雜度
o(logn)
,其中鍵不允許重複。
multimap 和
map一樣,區別是鍵可以重複
,比如兩種水果,蘋果和橘子,
**是一樣的。這時候multimap就有用武之地了。
連續記憶體的容器:這種型別容器包含
vector
、deque
。特點是在一塊連續的記憶體塊上存放資料,所以有資料插入和刪除的時候,如果不是在序列的或者兩端那麼花費的代價是非常大的,因為需要保證連續記憶體,同時給新元素騰出空間或者填充刪除元素的空間,如果儲存的是複雜結構的話就要花費大量的時間進行拷貝操作(可以儲存複雜結構的指標來彌補這個缺陷,這個討論在另個總結中進行)。
基於節點的容器:這類容器是剩餘的幾個
list
、set
、multiset
、map
、multimap.
這類容器中的資料是分別儲存在不同的記憶體塊中,可能連續也可能不連續(一般不認為是連續的),這樣的容器在插入刪除元素的時候修改的只是節點的指標,這樣的消耗是非常小的。
在使用這些容器時,需要考慮的因素
1.需要大量新增新元素:
vector
在大量新增元素的時候問題最大,因為他的一種最常見的記憶體分配實現方法是當前的容量
(capacity)
不足就申請一塊當前容量
2倍的新記憶體空間,然後將所有的老元素全部拷貝到新記憶體中,新增大量元素的時候的花費的驚人的大。如果由於其他因素必須使用
vector
,並且還需要大量新增新元素,那麼可以使用成員函式
reserve
來事先分配記憶體,這樣可以減少很多不必要的消耗。
list
對這種情況的適應能力就非常好,都是常數時間的插入消耗。
deque
前面說過了,他是
vector
和list
的折衷形式,記憶體不夠了就申請一塊新的記憶體,但並不拷貝老的元素。
2.查詢速度:
這個因素主要取決於演算法,而演算法最終是作用在容器中元素上的,所以這裡的查詢速度指的是容器能夠達到的最好查詢效率。
對於序列容器需要分兩種情況,區分依據是元素是否排序,
1)對於已經排序的序列容器,使用
binary_search
、lower_bound
、upper_bound
、equal_range
可以獲得對數時間複雜度的查詢速度
(o(logn));2)
而未排序的序列容器二分查詢肯定是用不了,能達到的最好的時間複雜度是線性的
(o(n))。
對於關聯容器,儲存的時候儲存的是一棵紅黑樹
(一種更為嚴格的平衡二叉樹
,文件最後有介紹
),總是能達到對數時間複雜度
(o(logn))
的效率,因為關聯容器是按照鍵值排好序的。
3.是否是連續記憶體:
連續記憶體的容器有個明顯的缺點,就是有新元素插入或老元素刪除的時候,為了給新元素騰出位置或者填充老元素的空缺,同一塊記憶體中的其他資料需要進行整體的移位,這種移位的拷貝代價有時是非常巨大的。標準容器中的
vector
、deque
是連續記憶體的,其中
vector
是完全連續記憶體,而
deque
是vector
和list
的折衷實現,是多個記憶體塊組成的,每個塊中存放的元素連續記憶體,而記憶體塊又像鍊錶一樣連線起來。
所以需要考慮在操作的過程中是否有在任意位置插入元素的需求,有這種需求的話盡量避免使用連續記憶體的
vector
、deque
4.元素的排序:
序列容器中的元素不會自動排序,程式設計師插入什麼順序記憶體中就是什麼順序,而關聯容器不是這樣的,他會以自己的鍵值按照某種等價關係
(equivalence)
進行排序。所以預設情況下序列容器中的元素是無序的,而關聯容器中的元素是有序的。
所以容器在遍歷元素的時候序列容器輸出的順序和插入的順序式一致的,關聯容器就不一定了。
1.vector
的資料模型就是陣列。
優點:記憶體和
c完全相容、高效隨機訪問、節省空間
缺點:內部插入刪除元素代價巨大、動態大小查過自身容量需要申請大量記憶體做大量拷貝。
2.list
的資料結構模型是鍊錶
優點:任意位置插入刪除元素常量時間複雜度、兩個容器融合是常量時間複雜度
缺點:不支援隨機訪問、比
vector
占用更多的儲存空間
3.deque
的資料模型是陣列和鍊錶的折衷:
優點:高效隨機訪問、內部插入刪除元素效率方便、兩端
push pop
缺點:記憶體占用比較高 4
.map
、set
、multimap
、multiset
的資料結構模型是二叉樹
(紅黑樹)
優點:元素會按照鍵值排序、查詢是對數時間複雜度、通過鍵值查元素、
map提供了下標訪問
1)如果需要隨機訪問,用
vector 2
)如果儲存元素的數目已知,用
vector 3
)需要任意位置隨機插入刪除,用
list 4
)只有需要更多在容器的首部尾部插入刪除元素,用
deque 5
)元素是複雜結構用
list
,也可以用
vector
儲存指標
(需要額外的精力去維護記憶體
),看需求 6
)如果操作是基於鍵值,用
set map 7
)如果需要經常的搜尋,用
mapset 8
)map set
的區別是
map中的元素都是
pair
,同時map
提供下標訪問
,也是個陷阱
STL容器的適用情況
一 各種容器的特性 vector 典型的序列容器,c 標準嚴格要求次容器的實現記憶體必須是連續的,唯一可以和標準c相容的stl容器,任意元素的讀取 修改具有常數時間複雜度,在序列尾部進行插入 刪除是常數時間複雜度,但在序列的頭部插入 刪除的時間複雜度是o n 可以 在任何位置插入新元素,有隨機訪問功...
Thread各方法適用情況
try catch interruptedexception e systemclock.sleep 2000 sleep 方法會使執行緒睡眠,交出cpu給其他執行緒使用。注意 sleep 方法不會釋放鎖。上述第二個方法為android獨有,兩者的區別就為是否catch interruptedexc...
C 與C STL的容器對應說明
dotnet 下的泛型容器類封裝在 system.collections.generic 使用的十分廣泛。c 則靠 stl實現了泛型容器與演算法。下面對二者做乙個對比,只談用法,不深究原理。對比的內容有陣列 鍊錶和字典三種結構。一 陣列 c 使用list c 用的是std vector 內部實現都是...