[C++ Primer Note10] 關聯(lián)容器

關聯(lián)容器和順序容器的本質區(qū)別在于:關聯(lián)容器中的元素是按關鍵字來保存和訪問的,而順序容器是按它們在容器中的位置來順序保存和訪問的味咳。

  1. 標準庫提供8個關聯(lián)容器

按關鍵字有序保存元素

  • map
  • set
  • multimap
  • multiset

無序集合

  • unordered_map
  • unordered_set
  • unordered_multimap
  • unordered_multiset

其中,multi表示允許重復關鍵字檬嘀。map和multimap定義在頭文件map中槽驶;set和multiset定義在set中;無需容器定義在頭文件unordered_mapunordered_set中鸳兽。

  1. 一個經典的使用關聯(lián)容器的例子是單詞計數(shù)程序
map<string,int> word_count;
string tmp;
while(cin>>tmp){
    ++word_count[tmp];
}

for(const auto &w:word_count){
    cout<<w.first<<":"<<w.second<<endl;
}

一旦讀取完所有輸入掂铐,范圍for語句就會遍歷map,當從map中提取一個元素時揍异,會得到一個pair類型的對象全陨,它是一個模板類型,保存兩個名為firstsecond的公有數(shù)據(jù)成員衷掷,前者為key辱姨,后者為value

  1. 上一個程序的一個合理拓展是:忽略常見單詞戚嗅,我們可以使用set保存想忽略的單詞雨涛,只對不在集合中的單詞統(tǒng)計出現(xiàn)次數(shù):
map<string,int> word_count;
set<string> exclude={"The","But","And"};
string tmp;
while(cin>>tmp){
    if(exclude.find(tmp)==exclude.end())
        ++word_count[tmp];
}

set的find成員返回一個迭代器。如果給定關鍵字在set中懦胞,迭代器指向該關鍵字替久。否則,find返回尾后迭代器躏尉。

  1. 對于有序容器蚯根,關鍵字類型必須定義元素比較的方法,默認情況下胀糜,標準庫使用關鍵字類型的<運算符來比較兩個關鍵字稼锅。當然也可以自定義比較規(guī)則:
multiset<Sales_data,decltype(compareIsbn)*> bookstore(compareIsbn);

需要提供比較操作類型(一種函數(shù)指針類型),以及在構造函數(shù)中傳入比較函數(shù)

  1. pair標準庫類型僚纷,定義在頭文件utility中矩距,一個pair保存兩個數(shù)據(jù)成員。pair的默認構造函數(shù)對數(shù)據(jù)成員進行值初始化怖竭,我們可以這樣初始化pair:
pair<string,string> author{"james","kevin"};
pair<int,string> student(1,"kevin");
  1. 關聯(lián)容器額外定義了幾個類型別名
  • key_type:關鍵字類型
  • mapped_type:每個關鍵字關聯(lián)的類型
  • value_type:對于set锥债,就是key_type;對于map,是pair類型
  1. 當解引用一個關聯(lián)容器迭代器時哮肚,我們會得到一個類型為容器的value_type的值得引用登夫。
  2. set的迭代器是const的 ,無論是iterator還是const_iterator允趟。而map的pair中的第一個成員也是const的恼策。
  3. map和set類型都支持前述的beginend操作,對于有序關聯(lián)容器來說潮剪,按照關鍵字升序遍歷涣楷。
  4. 我們通常不對關聯(lián)容器使用泛型算法,關鍵字是const這一特性意味著不能將關聯(lián)容器傳遞給修改或重排容器元素的算法抗碰。對于搜索算法而言狮斗,泛型算法是順序搜索,而關聯(lián)容器內部定義的find成員根據(jù)關鍵字搜索會快得多弧蝇。
    一般來說碳褒,僅在把關聯(lián)容器當作源序列或者目的位置的時候才使用泛型算法。
  5. 添加元素
    添加元素
// 插入一個元素到map中
word_count.insert({word,1});
word_count.insert(make_pair(word,1));
word_count.insert(pair<string,size_t>(word,1));
word_count.insert(map<string,size_t>::value_type(word,1));
  1. insert(或emplace)返回值依賴于容器類型和參數(shù)看疗,對于不包含重復關鍵字的容器沙峻,添加單一元素的insert和emplace返回一個pair,first成員是一個指向給定關鍵字的迭代器(即使插入失斄椒肌)摔寨,second成員是一個bool,如果插入之前key已經存在返回false盗扇,否則插入成功返回true。對于允許重復關鍵字的容器沉填,insert操作僅僅返回一個指向新元素的迭代器疗隶,沒有bool值
  2. 刪除元素
    刪除元素
  3. map的下標操作
    下標操作

    我們不能對multi版本的map進行下標操作翼闹,因為可能有多個值相關聯(lián)斑鼻。
    下標運算符在關鍵字不存在的情況下會創(chuàng)建元素并插入到map
  4. 與迭代器不同猎荠,map的下標操作返回的是mapped_type而不是解引用迭代器得到的value_type坚弱。
  5. 查找元素
    查找元素

    我們可以通過lower_boundupper_bound找到一個關鍵字相同的序列(對于multi來說)
  6. 新標準定義了4個無序關聯(lián)容器,這些容器不是使用比較運算符(樹)來組織元素关摇,而是使用哈希函數(shù)和關鍵字類型的==運算符荒叶。在關鍵字類型的元素沒有明顯的序關系的情況下,無序容器非常有用输虱。
    無序容器無非就是一組桶些楣,除了提供與有序容器相同的操作之外,它還提供了一組管理桶的成員函數(shù),這些成員函數(shù)允許我們查詢容器的狀態(tài)以及在必要時強制容器進行重組:
    無序容器管理操作
  7. 默認情況下愁茁,無序容器使用關鍵字類型的==運算符來比較元素蚕钦,它們還使用一個hash<key_type>類型的對象來生成每個元素的哈希值。標準庫為內置類型(包括指針)提供了hash模板鹅很。還為一些標準庫類型嘶居,包括string和智能指針類型定義了hash。因此促煮,我們可以直接定義關鍵字是內置類型邮屁,string以及智能指針的無序容器。
  8. 但是污茵,我們不能直接定義關鍵字類型為自定義類型的無序容器樱报,與容器不同,不能直接使用哈希模板泞当,而必須提供我們自己的hash模板版本迹蛤。但我們可以使用類似于為有序容器重載關鍵字類型的方法提供函數(shù)代替==運算符和哈希值計算函數(shù)去實現(xiàn)同樣的效果。
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末襟士,一起剝皮案震驚了整個濱河市盗飒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌陋桂,老刑警劉巖逆趣,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異嗜历,居然都是意外死亡宣渗,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門梨州,熙熙樓的掌柜王于貴愁眉苦臉地迎上來痕囱,“玉大人,你說我怎么就攤上這事暴匠“盎郑” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵每窖,是天一觀的道長帮掉。 經常有香客問我,道長窒典,這世上最難降的妖魔是什么蟆炊? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮瀑志,結果婚禮上盅称,老公的妹妹穿的比我還像新娘肩祥。我一直安慰自己,他們只是感情好缩膝,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布混狠。 她就那樣靜靜地躺著,像睡著了一般疾层。 火紅的嫁衣襯著肌膚如雪将饺。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天痛黎,我揣著相機與錄音予弧,去河邊找鬼。 笑死湖饱,一個胖子當著我的面吹牛掖蛤,可吹牛的內容都是我干的。 我是一名探鬼主播井厌,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蚓庭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了仅仆?” 一聲冷哼從身側響起器赞,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎墓拜,沒想到半個月后港柜,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡咳榜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年夏醉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涌韩。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡畔柔,死狀恐怖,靈堂內的尸體忽然破棺而出贸辈,到底是詐尸還是另有隱情释树,我是刑警寧澤肠槽,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布擎淤,位于F島的核電站,受9級特大地震影響秸仙,放射性物質發(fā)生泄漏嘴拢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一寂纪、第九天 我趴在偏房一處隱蔽的房頂上張望席吴。 院中可真熱鬧赌结,春花似錦、人聲如沸孝冒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽庄涡。三九已至量承,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間穴店,已是汗流浹背撕捍。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留泣洞,地道東北人忧风。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像球凰,于是被迫代替她去往敵國和親狮腿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內容

  • #include set,multiset #include map,multimap #include unor...
    龍遁流閱讀 342評論 0 2
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,516評論 1 51
  • 九.順序容器 順序容器的順序表示元素插入的順序 C++標準庫容器提供了順序訪問元素的能力弟蚀,但是不同的容器在以下的操...
    m風滿樓閱讀 365評論 0 0
  • 在 ion-card中,有時候ion-item的高度對于手機來說有點高,有兩個地方可以調整,可以同時更改兩個參數(shù),...
    美味小魚閱讀 3,947評論 1 0
  • 我走進教室蚤霞,我覺得教室里又悶又熱,仿佛被502膠水凝固了义钉,我非常難受昧绣,我好像在沙漠中,那里非常熱捶闸,我快被shai死...
    摩天大樓8歲閱讀 277評論 0 0