STL常用容器內部實現

2021-08-13 08:06:12 字數 2557 閱讀 7058

stl是c/c++開發中乙個非常重要的模板,而其中定義的各種容器也是非常方便我們大家使用。下面,我們就**某些常用的容器。這裡我們不涉及容器的基本操作之類,只是要討論一下各個容器其各自的特點。stl中的常用容器包括:順序性容器(vector、deque、list)、關聯容器(map、set)、容器介面卡(queue、stac)。

1、順序性容器

(1)vector

vector是一種動態陣列,在記憶體中具有連續的儲存空間,支援快速隨機訪問。由於具有連續的儲存空間,所以在插入和刪除操作方面,效率比較慢。vector有多個建構函式,預設的建構函式是構造乙個初始長度為0的記憶體空間,且分配的記憶體空間是以2的倍數動態增長的,即記憶體空間增長是按照20,21,22,23.....增長的,在push_back的過程中,若發現分配的記憶體空間不足,則重新分配一段連續的記憶體空間,其大小是現在連續空間的2倍,再將原先空間中的元素複製到新的空間中,效能消耗比較大,尤其是當元素是非內部資料時(非內部資料往往構造及拷貝建構函式相當複雜)。vector的另乙個常見的問題就是clear操作。clear函式只是把vector的size清為零,但vector中的元素在記憶體中並沒有消除,所以在使用vector的過程中會發現記憶體消耗會越來越多,導致記憶體洩露,現在經常用的方法是swap函式來進行解決:  vectorv;

v.push_back(1); v.push_back(2);v.push_back(1); v.push_back(2);

vector().swap(v); 或者 v.swap(vector());

利用swap函式,和臨時物件交換,使v物件的記憶體為臨時物件的記憶體,而臨時物件的記憶體為v物件的記憶體。交換以後,臨時物件消失,釋放記憶體。

(2)deque

deque和vector類似,支援快速隨機訪問。二者最大的區別在於,vector只能在末端插入資料,而deque支援雙端插入資料。deque的記憶體空間分布是小片的連續,小片間用鍊錶相連,實際上內部有乙個map的指標。deque空間的重新分配要比vector快,重新分配空間後,原有的元素是不需要拷貝的。

(3)list

list是乙個雙向鍊錶,因此它的記憶體空間是可以不連續的,通過指標來進行資料的訪問,這使list的隨機儲存變得非常低效,因此list沒有提供操作符的過載。但list可以很好地支援任意地方的插入和刪除,只需移動相應的指標即可。

(4)在實際使用時,如何選擇這三個容器中哪乙個,應根據你的需要而定,一般應遵循下面的原則:

1) 如果你需要高效的隨即訪問,而不在乎插入和刪除的效率,使用vector

2) 如果你需要大量的插入和刪除,而不關心隨即訪問,則應使用list

3) 如果你需要隨即訪問,而且關心兩端資料的插入和刪除,則應使用deque

2、關聯容器

(1)map

map是一種關聯容器,該容器用唯一的關鍵字來對映相應的值,即具有key-value功能。map內部自建一棵紅黑樹(一種自平衡二叉樹),這棵樹具有資料自動排序的功能,所以在map內部所有的資料都是有序的,以二叉樹的形式進行組織。這是map的模板:

template < class key, class t, class compare= less, class allocator=allocator< pair> > class map;

從模板中我們可以看出,再構造map時,是按照一定的順序進行的。map的插入和刪除效率比其他序列的容器高,因為對關聯容器來說,不需要做記憶體的拷貝和移動,只是指標的移動。由於map的每個資料對應紅黑樹上的乙個節點,這個節點在不儲存你的資料時,是占用16個位元組的,乙個父節點指標,左右孩子指標,還有乙個列舉值(標示紅黑色),所以map的其中的乙個缺點就是比較占用記憶體空間。

(2)set

set也是一種關聯性容器,它同map一樣,底層使用紅黑樹實現,插入刪除操作時僅僅移動指標即可,不涉及記憶體的移動和拷貝,所以效率比較高。set中的元素都是唯一的,而且預設情況下會對元素進行公升序排列。所以在set中,不能直接改變元素值,因為那樣會打亂原本正確的順序,要改變元素值必須先刪除舊元素,再插入新元素。不提供直接訪問元素的任何操作函式,只能通過迭代器進行間接訪問。set模板原型:

template , class alloc=stl_default_allocator(key) > class set;

set支援集合的交(set_intersection)、差(set_difference)、並(set_union)及對稱差(set_symmetric_difference) 等一些集合上的操作。

3、容器介面卡

(1)queue

queue是乙個佇列,實現先進先出功能,queue不是標準的stl容器,卻以標準的stl容器為基礎。queue是在deque的基礎上封裝的。之所以選擇deque而不選擇vector是因為deque在刪除元素的時候釋放空間,同時在重新申請空間的時候無需拷貝所有元素。其模板為:

template < typename _sequence="deque<_tp" typeneam _tp,> > class queue;

(2)stack

stack是實現先進後出的功能,和queue一樣,也是內部封裝了deque,這也是為啥稱為容器介面卡的原因吧(純屬猜測)。自己不直接維護被控序列的模板類,而是它儲存的容器物件來為它實現所有的功能。stack的源**原理和實現方式均跟queue相同。

STL個各個容器的內部實現

連續空間 像陣列一樣 只能向尾端插入,空間可以增長,空間增長是乙個非常好效能的事 增長三部曲 另覓更大空間 將原資料複製過去 釋放原空間三部曲 環形雙向鍊錶 deque空間是分段連續,給人造成一種連續的假象,每乙個元素都是指標,指向另外一段真正連續的空間 稱作緩衝區 緩衝區才是真正存放資料的地方,因...

STL常用容器對比

stl的常用容器大致有以下8個 vector是一種動態陣列,在記憶體中具有連續的儲存空間,支援快速隨機訪問。由於具有連續的儲存空間,所以在插入和刪除操作方面,效率比較慢。vector有多個建構函式,預設的建構函式是構造乙個初始長度為0的記憶體空間,且分配的記憶體空間是以2的倍數動態增長的,在push...

STL常用容器解析

關鍵字 key 無序 關聯容器 刷題過程中,有兩個步驟最為關鍵 1 思路與解析,一道題能否找到解題的思路決定了能否做的出來,有明晰的思路就能夠腦海裡通過演算法與資料結構的知識去分解為每乙個小process,然後去解析實現直到最終結果,只有豐富的演算法經驗,才能在刷題過程中游刃有餘,逐個擊破!2 實現...