我們學習過順序容器如vecor,list等,它們中的元素是按照在容器中的位置來順序儲存和訪問的。而接下來要學習的關聯容器則有根本的不同,它們中的元素是按關鍵字來儲存和訪問的。
在《c++primer》中列舉了標準庫中的8個關聯容器,如下:
關聯容器支援高效的關鍵字查詢和訪問,我們在這裡介紹兩個主要的關聯容器set和map。
map裡面存的是一些key-value對,其中key起到索引的作用, 而value則表示於索引相關聯的資料。
比如字典就是乙個很好使用map的例子,把單詞當作key,解釋當作value。其實map型別也常稱做關聯陣列,它和一般的陣列類似,可以認為它key就是陣列的下標(只不過不必是整數),value則是陣列存的值,還是上面的字典例子,比如有某個單詞為right,它的其中乙個解釋為右邊的,我們就可以使用類似陣列的方式a[「right」]訪問到「右邊的」這個解釋。
set裡面每個元素只存有乙個key,它支援高效的關鍵字查詢操作,比如檢查乙個關鍵字是否在set中或者在
某些文字處理過程中可用set儲存想要忽略的單詞
在學習這兩種關聯容器之前,我們可以先看一兩個如何使用這類容器的例子。
假設乙個字串陣列,裡面的每個字串都是水果,比如蘋果,梨子等,現在要統計每種水果出現的次數。
string fruit =
;size_t n = sizeof(fruit) / sizeof(fruit[0]);
map countfruit;//定義map用來訪問每種水果和它的次數
for (size_t i = 0; i < n; ++i)//增加每種水果的次數
for (const
auto& element : countfruit)//列印每種水果以及它的次數
對於上面的程式,首先定義了乙個map來訪問每種水果和它的次數,map也是模板,我們必須指定key和value,在這個程式中,key為string表示水果,value為size_t表示次數。
此時map裡面的每個元素都是乙個pair型別的物件,簡單來說pair是個模版型別,儲存兩個public成員first和second分別對應key和value。
在上面我們說過,可以通過a[key]訪問到value,因此在本例中,我們類似的也用countfruit[fruit[i]]訪問到次數,但是需要注意的一點是,如果當前fruit[i]還不在map中,則建立新元素,且它的key為fruit[i],value為0。不管元素是否是新建立的,我們都將value加1。
最後的列印操作,我們使用了範圍for語句,訪問到map的每個元素(pair型別),然後列印他們的key和value。結果如下圖:
上乙個例子我們進行乙個簡單的擴充套件,比如可能某種水果太貴了比如pear,watermelon等等,我們忽視這些輸入,我們則可以用set儲存要想要忽略的單詞,只對不在set集合的單詞統計次數。
map
countfruit;//定義map用來訪問每種水果的次數
set exclude = ;
for (size_t i = 0; i < n; ++i)
我們定義了乙個set用來儲存需要忽略的元素,類似的set也是乙個模板,我們需要傳入乙個key型別。這個程式僅僅是多加了一句if,我們來看看是怎麼回事。我們呼叫它的find函式,它返回乙個迭代器,如果給定key在set中,則迭代器指向該key,不然返回尾後迭代器以表示沒找到。這裡面我們就完成了僅當每種水果不在忽略集合中再統計它的次數。結果如下圖:
看完了上面的例子,我們對map和set有了乙個大致的了解,下面我們僅對一些常用操作進行介紹,其餘的可以參考c++文件查詢map和set完整詳細用法。
在上面,我們對map和set進行了乙個說明,map是以key-value的形式訪問,set以key形式訪問,他們的底層都是以紅黑樹的結構實現,因此插入刪除等操作都在o(logn)時間內完成,因此可以完成高效的插入刪除。
由於是他們的底層是紅黑樹,因此在插入時候他們會預設執行排序操作,且他們key都是唯一的,因此從這個角度看,他們在某種程度上可以實現過濾重複值和排序(預設公升序)的功能。
這是按照字元ascii碼的順序公升序得到的,因此有時候也可以讓map/set排序。
但是,如果想要改變預設次序,我們可以對map/set的建構函式傳入乙個函式物件進行降序,下面我們來看看它的一些建構函式和拷貝建構函式。
bool fncomp (char lhs, char rhs)
了解map構造,我們來看下最常用的insert和find操作, 在之前的統計水果次數題,我們插入元素使用操作,現在我們換種做法:
void countfruittimes(map
& countfruit, string fruit, size_t n)
//countfruit[fruit[i]]++;}}
我們寫了個函式完成統計次數的功能,注意到insert返回的是pair型別,它的first為乙個迭代器,second為bool型別,如果bool為true說明插入成功,此時它的key為fruit[i],value為1。如果bool為false說明插入失敗,說明該元素已經存在,但是我們可以通過insert返回值ret得到指向該元素的迭代器。
記得之前我們講過map裡面每個元素都是乙個pair型別,在上面的例子中第乙個為string,第二個是size_t,因此ret.first為迭代器訪問到size_t成員並對次數加1。
這樣就完成了統計次數的操作。
STL庫 set和map的使用和原理
set和map是c 標準庫中的關聯容器,它們中的所有元素都會根據元素的鍵值 key 自動被排序,又由於紅黑樹 rb tree 是一種平衡二叉搜尋樹,自動排序效果非常好,所以標準的stl中的set和map容器都是以紅黑樹 rb tree 為底層機制,又由於map和set所開放的各種操作介面,rb tr...
Map和Set簡單使用
map 和set的底層就是紅黑樹,map是k,v模型,而set是k模型。以上就是map的內部實現的成員函式,構造,插入刪除,等。map作為k,v模型,可以有很多用途,比如實現乙個字典。map實現乙個字典 include using namespace std include include int ...
Map和Set簡單使用
map 和set的底層就是紅黑樹,map是k,v模型,而set是k模型。以上就是map的內部實現的成員函式,構造,插入刪除,等。map作為k,v模型,可以有很多用途,比如實現乙個字典。map實現乙個字典 include using namespace std include include int ...