C++primer第十一章 關聯容器 11.1使用關聯容器 11.2 關聯容器概述

  • 關聯容器和順序容器有著根本的不同:關聯容器中的元素是按關鍵字來保存和訪問的。與之相對,順序容器中的元素是按它們在容器中的位置來順序保存和訪問的
  • 雖然關聯容器的很多行為與順序容器相同,但其不同之處反映了關鍵字的作用
  • 關聯容器支持高效的關鍵字查找和訪問。兩個主要的關聯容器(associative-container)類型是map和set。map中的元素是一些關鍵字-值(key-value)對關鍵字起到索引的作用,值則表示與索引相關聯的數據。set中每個元素只包含一個關鍵字;set支持高效的關鍵字查詢操作--檢查一個給定關鍵字是否在set中。例如,在某些文本處理過程中,可以用一個set來保存想要忽略的單詞。字典則是一個很好的使用map的例子:可以將單詞作為關鍵字,將單詞釋義作為值。
  • 標準庫提供8個關聯容器,如表11.1所示。這8個容器間的不同體現在三個維度上:每個容器
  • (1)或者是一個set,或者是一個map;
  • (2)或者要求不重復的關鍵字,或者允許重復關鍵字;
  • (3)按順序保存元素,或無序保存。允許重復關鍵字的容器的名字中都包含單詞multi;不保持關鍵字按順序存儲的容器的名字都以單詞unordered開頭。因此一個unordered_multi_set是一個允許重復關鍵字,元素無序保存的集合,而一個set則是一個要求無重復關鍵字,有序存儲的集合。無序容器使用哈希函數來組織元素,我們將在11.4節(第394頁)中詳細介紹有關哈希函數的更多內容。
  • 類型map和multimap定義在頭文件map中;set和multiset定義在頭文件set中;無序容器則定義在頭文件unordered_map和unordered_set中。

11.1使用關聯容器

  • 雖然大多數程序員都熟悉諸如vector和list這樣的數據結構,但他們中很多人從未使用過關聯數據結構。在學習標準庫關聯容器類型的詳細內容之前,我們首先來看一個如何使用這類容器的例子,這對后續學習很有幫助。
  • map是關鍵字-值對的集合。例如,可以將一個人的名字作為關鍵字,將其電話號碼作為值。我們稱這樣的數據結構為"將名字映射到電話號碼”。map類型通常被稱為關聯數組。關聯數組與''正常”數組類似,不同之處在于其下標不必是整數。我們通過一個關鍵字而不是位置來查找值。給定一個名字到電話號碼的map,我們可以使用一個人的名字作為下標來獲取此人的電話號碼。
  • 與之相對,set就是關鍵字的簡單集合。當只是想知道一個值是否存在時,set是最有用的。例如,一個企業可以定義一個名為bad_checks的set來保存那些曾經開過空頭支票的人的名字。在接受一張支票之前,可以查詢bad_checks來檢查顧客的名字是否在其中。

?

  • 此程序讀取輸入,報告每個單詞出現多少次。
  • 類似順序容器,關聯容器也是模板(參見3.3節,第86頁)。為了定義一個map,我們必須指定關鍵字和值的類型。在此程序中,map保存的每個元素中,關鍵字是string類型,值是size_t類型(參見3.5.2節,第103頁)。當對word_count進行下標操作時,我們使用一個string作為下標,獲得與此string相關聯的size_t類型的計數器。while循環每次從標準輸入讀取一個單詞。它使用每個單詞對word_count進行下標操作。如果word還未在map中,下標運算符會創建一個新元素,其關鍵字為word,值為0。不管元素是否是新創建的,我們將其值加1
  • 一旦讀取完所有輸入,范圍for語句(參見3.2.3節,第81頁)就會遍歷map,打印每個單詞和對應的計數器。當從map中提取一個元素時,會得到一個pair類型的對象,我們將在11.2.3節(第379頁)介紹它。簡單來說,pair是一個模板類型,保存兩個名為first和second的(公有)數據成員。map所使用的pair用first成員保存關鍵字,用second成員保存對應的值。因此,輸出語句的效果是打印每個單詞及其關聯的計數器。

使用 set

  • 上一個示例程序的一個合理擴展是:忽略常見單詞,如"the", "and", "or"等。我們可 以使用set保存想忽略的單詞,只對不在集合中的單詞統計出現次數:

  • 與其他容器類似,set也是模板。為了定義一個set,必須指定其元素類型,本例中是string。與順序容器類似,可以對一個關聯容器的元素進行列表初始化(參見9.2.4節,第300頁)。集合exclude中保存了12個我們想忽略的單詞。此程序與前一個程序的重要不同是,在統計每個單詞出現次數之前,我們檢查單詞是否在忽略集合中,這是在if語句中完成的:
  • find調用返回一個迭代器。如果給定關鍵字在set中,迭代器指向該關鍵字。否則,find 返回尾后迭代器。在此程序中,僅當word不在exclude中時我們才更新word的計數器。

1 1 .2 關聯容器概述

  • 關聯容器(有序的和無序的)都支持9.2節 (第 294頁)中介紹的普通容器操作(列于表9.2,第 295頁)。關聯容器不支持順序容器的位置相關的操作,例如push_front 或 push_back。原因是關聯容器中元素是根據關鍵字存儲的,這些操作對關聯容器沒有意義。而且,關聯容器也不支持構造函數或插入操作這些接受一個元素值和一個數量值的操作
  • 除了與順序容器相同的操作之外,關聯容器還支持一些順序容器不支持的操作(參見表 11.7,第 388頁)和類型別名(參見表11.3,第 381頁)。此外,無序容器還提供一些
  • 用來調整哈希性能的操作,我們將在11.4節 (第 394頁)中介紹。關聯容器的迭代器都是雙向的(參見10.5.1節,第 365頁)。

11.2.1定義關聯容器

  • 如前所示,當定義一個map時,必須既指明關鍵字類型又指明值類型;而定義一個set時,只需指明關鍵字類型,因為set中沒有值。每個關聯容器都定義了一個默認構造函數,它創建一個指定類型的空容器。我們也可以將關聯容器初始化為另一個同類型容器的拷貝,或是從一個值范圍來初始化關聯容器,只要這些值可以轉化為容器所需類型就可以。在新標準下,我們也可以對關聯容器進行值初始化

  • 與以往一樣,初始化器必須能轉換為容器中元素的類型。對于set,元素類型就是關鍵字類型。
  • 當初始化一個map時,必須提供關鍵字類型和值類型。我們將每個關鍵字-值對包圍在花括號中:{key,value}來指出它們一起構成了map中的一個元素。在每個花括號中,關鍵字是第一個元素,值是第二個。因此,authors將姓映射到名,初始化后它包含三個元素。

初始化multimap或multiset

  • 一個map或set中的關鍵字必須是唯一的,即,對于一個給定的關鍵字,只能有一個元素的關鍵字等于它。容器multimap和multiset沒有此限制,它們都允許多個元素具有相同的關鍵字。例如,在我們用來統計單詞數量的map中,每個單詞只能有一個元素。另一方面,在一個詞典中,一個特定單詞則可具有多個與之關聯的詞義。
  • 下面的例子展示了具有唯一關鍵字的容器與允許重復關鍵字的容器之間的區別。首先,我們將創建一個名為ivec的保存int的vector,它包含20個元素:0到9每個整數有兩個拷貝。我們將使用此vector初始化一個set和一個multiset:

  • 即使我們用整個ivec容器來初始化iset,它也只含有10個元素:對應ivec中每個不同的元素。另一方面,miset有 20個元素,與 ivec中的元素數量一樣多。

11.2.2關鍵字類型的要求

  • 關聯容器對其關鍵字類型有一些限制。對于無序容器中關鍵字的要求,我們將在11.4節 (第 396頁)中介紹。對于有序容器map、multimap, ?set以及multiset,關鍵字類型必須定義元素比較的方法。默認情況下,標準庫使用關鍵字類型的 < 運算符來比較兩個關鍵字。在集合類型中,關鍵字類型就是元素類型;在映射類型中,關鍵字類型是元素的第一部分的類型。因此,11.2節 (第 377頁)中 word_count的關鍵字類型是 string.類似的,exclude的關鍵字類型也是string。
  • 傳遞給排序算法的可調用對象(參見10.3.1節,第344頁)必須滿足與關聯容器中關鍵字一樣的類型要求。

有序容器的關鍵字類型

  • 可以向一個算法提供我們自己定義的比較操作(參見10.3節,第344頁),與之類似,也可以提供自己定義的操作來代替關鍵字上的<運算符。所提供的操作必須在關鍵字類型
    上定義一個嚴格弱序(strictweakordering)。可以將嚴格弱序看作"小于等于”,雖然實際定義的操作可能是一個復雜的函數。無論我們怎樣定義比較函數,它必須具備如下基本性質:
  • 兩個關鍵字不能同時“小于等于”對方;如果kl"小于等于”k2,那么k2絕不能“小于等于”kl。
  • 如果kl“小于等于”k2,且k2“小于等于”k3,那么kl必須“小于等于”k3。
  • 如果存在兩個關鍵字,任何一個都不"小于等于"另一個,那么我們稱這兩個關鍵字是"等價”的。如果kl“等價于”k2,且k2“等價于”k3,那么kl必須“等價于”k3
  • 如果兩個關鍵字是等價的(即,任何一個都不“小于等于”另一個),那么容器將它們視作相等來處理。當用作map的關鍵字時,只能有一個元素與這兩個關鍵字關聯,我們可以用兩者中任意一個來訪問對應的值。

使用關鍵字類型的比較函數

  • 用來組織一個容器中元素的操作的類型也是該容器類型的一部分。為了指定使用自定義的操作,必須在定義關聯容器類型時提供此操作的類型。如前所述,用尖括號指出要定義哪種類型的容器,自定義的操作類型必須在尖括號中緊跟著元素類型給出。
  • 在尖括號中出現的每個類型,就僅僅是一個類型而已。當我們創建一個容器(對象)時,才會以構造函數參數的形式提供真正的比較操作(其類型必須與在尖括號中指定的類型相吻合)

  • 此處,我們使用decltype來指出自定義操作的類型。記住,當用decltype來獲得一個函數指針類型時,必須加上一個*來指出我們要使用一個給定函數類型的指針(參見6.7節,第223頁)。用comparelsbn來初始化bookstore對象,這表示當我們向bookstore添加元素時,通過調用comparelsbn來為這些元素排序。即bookstore中的元素將按它們的ISBN成員的值排序。可以用comparelsbn代替&comparelsbn作為構造函數的參數,因為當我們使用一個函數的名字時,在需要的情況下它會自動轉化為一個指針(參見6.7節,第221頁)。當然,使用&comparelsbn的效果也是一樣的。

11.2.3pair類型

  • 在介紹關聯容器操作之前,我們需要了解名為pair的標準庫類型,它定義在頭文件utility中。
  • 一個pair保存兩個數據成員。類似容器,pair是一個用來生成特定類型的模板。當創建一個pair時,我們必須提供兩個類型名,pair的數據成員將具有對應的類型。兩個類型不要求一樣:

  • pair的默認構造函數對數據成員進行值初始化(參見3.3.1節,第 88頁)。因此,anon是一個包含兩個空string的 pair, line保存一個空string和一個空vector。 word_count中的size_t成員值為0,而 string成員被初始化為空。我們也可以為每個成員提供初始化器:
  • pair<string, string> author( "James", ”Joyce”};
  • 這條語句創建一個名為author的pair,兩個成員被初始化為"James"和"Joyce”。與其他標準庫類型不同,pair的數據成員是public的(參見7.2節,第240頁)。兩個成員分別命名為first和second。我們用普通的成員訪問符號(參見1.5.2節,第20頁)來訪問它們,例如,在第375頁的單詞計數程序的輸出語句中我們就是這么做的:
  • cout<<w.first << " occurs" << w.second<<((w.second>1)?"times":"time")<<endl;
  • 此處,w是指向map中某個元素的引用。map的元素是pair.在這條語句中,我們首先打印關鍵字元素的first成員,接著打印計數器second成員。標準庫只定義了有限的幾個pair操作,表11.2列出了這些操作。

創建pair對象的函數

  • 用想象有一個函數需要返回一個pair。在新標準下,我們可以對返回值進行列表初始化(參見6.3.2節,第203頁)
pair<string, int>
process(vector<string> &v)
(
/ / 處理v
if (!v.empty())
return {v.back () , v.back () .size () }; // 列表初始化
else
return pair<stringz int> () ; // 隱式構造返回值
}
  • 若v 不為空,我們返回一個由v 中最后一個string及其大小組成的pair。否則,隱式構造一個空pair,并返回它。 在較早的C++版本中,不允許用花括號包圍的初始化器來返回pair這種類型的對象, 必須顯式構造返回值:

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/446693.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/446693.shtml
英文地址,請注明出處:http://en.pswp.cn/news/446693.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

codeforces 791A-C語言解題報告

791A題目網址 題目解析 1.輸入a,b,每一年a3;b2,問多少年a>b? 2.因為不知道需要循環多少次,使用while循環 代碼 #include<stdio.h> #include<stdlib.h> #include<string.h> int main() {int a,b,i0;scanf("%d %d",&a,&b);while(a&l…

Redis Mac下安裝與使用

目錄一、下載安裝包二、編譯三、服務端與客戶端命令1、服務端啟動命令2、客戶端連接命令3、服務端關閉命令一、下載安裝包 官網地址&#xff1a;http://redis.io/download 下載后&#xff0c;解壓放到任意目錄下。 二、編譯 打開終端&#xff0c;切換到 Redis 根目錄&#x…

C++primer第十一章 關聯容器 11.3關聯容器操作 11.4 無序容器

11.3關聯容器操作 除了表9.2(第295頁)中列出的類型&#xff0c;關聯容器還定義了表11.3中列出的類型。這些類型表示容器關鍵字和值的類型。對于set類型&#xff0c;key_type和value type是一樣的&#xff1b;set中保存的值就是關鍵字。在一個map中&#xff0c;元素是關鍵字_值…

codeforces 977A-C語言解題報告

977A題目網址 題目解析 1,輸入數字n,運算次數k,當n最后一個數字是0時,n/10;當n最后一個數字不是0時,n-1;輸出n 舉例: 輸入: 512 4 輸出: 50 2.注意:當n最后一個數字是0時,使用n%100去判斷 代碼 #include<stdio.h> #include<stdlib.h> #include<string.h>…

SpringBoot 整合Dubbo

文章目錄一、工程目錄結構二、創建工程項目1、創建接口工程&#xff08;cw-dubbo-api&#xff09;&#xff08;1&#xff09;pom.xml&#xff08;2&#xff09;創建接口類&#xff08;LoginService&#xff09;2、創建服務提供者工程&#xff08;cw-dubbo-provider&#xff09;…

macos實現輸入文件輸入結束符

在clion軟件中&#xff0c;執行cin>>value ,如何手動輸入結束符號&#xff1f;&#xff1f;需要在debug環境下&#xff0c;然后&#xff0c;使用command D 實現此功能

2000年考研英語閱讀理解文章二

文章詳細解析 注意點 1.文章標題選擇,查看文章中一直在重復提及的話語: 如:我們沒有進化了—>標題:人類進化無路可走 知識點 ----單詞 1.offspring n孩子,后代 2.Utopia n烏托邦,空想的完美境界 3.wholly adv完全地 4.comprehension n理解力 5.descendant n后代 6.mate …

Kafka Mac下安裝與使用

文章目錄一、下載安裝二、啟動Zookeeper三、啟動Kafka四、創建Topic五、查看Topic六、刪除Topic七、生產/消費數據八、查看消費組九、查看消費組詳情一、下載安裝 到 Kafka 官網下載&#xff1a;https://kafka.apache.org/downloads 下載好 tar包 后&#xff0c;執行下面命令…

C++primer第一章 開始

運算符打印endl,這是一個被稱為操縱符(manipulator)的特殊值。寫入endl 的效果是結束當前行&#xff0c;并將與設備關聯的緩沖區(buffer)中的內容刷到設備中。緩沖刷新操作可以保證到目前為止程序所產生的所有輸出都真正寫入輸出流中&#xff0c;而不是僅停留在內存中等待寫入流…

codeforces 617A-C語言解題報告

617A題目網址 題目解析 1.輸入x,能夠通過1,2,3,4,5去到達x,求最小到達x的步數. 舉例: 輸入: 12 輸出: 3 2.注意點: 要最小的步數,所以直接使用最大的5去比較判斷 1)當x<5時,只需要1 2)當x>5時,如果x%50(x能整除5),只需要x/5步數,不能整除則需要x/51步數 代碼 #inclu…

SpringBoot —— Bean的注入方式

文章目錄1、組件注解2、Component Bean3、Import(PlaceHolderClass)快速導入一個組件4、使用Spring提供的FactoryBean注入1、組件注解 注解描述Component組件定義不清晰時候的注解Controller控制器層Service服務層Repository數據層 注&#xff1a;添加注解的類需要與啟動類在…

如何保養電池

1&#xff0c;不要在低于0度和高于35度的范圍下使用電池&#xff0c;尤其是高溫環境下對電腦充電&#xff0c;對電池的破壞是不可逆轉的。2&#xff0c;放電過于徹底或者充電過于飽和&#xff0c;也會對電池的容量造成損耗。BMS 調整電池的充放電3&#xff0c;電腦長期不用&…

codeforces 116A-C語言解題報告

116A題目網址 題目解析 1.輸入n(n個循環),每一個循環-a,b;第一個循環只有b;最后一個循環只有-a;求其中在車上的最大人數? 舉例: 輸入: 4 0 3 2 5 4 2 4 0 輸出: 6 2.注意點:因為使用count計數時,count一直在改變,所以再加入一個max變量去記錄count中出現的最大數. 代碼 #…

SpringBoot —— @ComponentScan注解

文章目錄一、作用二、注解屬性說明三、使用方式一、作用 主要是從定義的掃描路徑中&#xff0c;找出標識了需要裝配的類自動裝配到Spring的bean容器中。 簡單的說就是 ComponentScan告訴Spring從哪里找到bean&#xff0c;一旦指定了&#xff0c;Spring就會將指定的包及其下級…

硬盤 相關知識

磁盤存儲數據于軌道上&#xff0c;為了防止數據不被干擾&#xff0c;軌道之間是存在間隙的。如果間隙越小存儲的數據越多&#xff0c;但是對數據的寫入和讀取所使用的磁頭是不一樣的&#xff0c;寫入的磁頭比較寬&#xff0c;讀取的磁頭比較窄。疊瓦式硬盤&#xff0c;將軌道和…

Java 序列化反序列化框架比較

文章目錄一、簡介二、序列化框架1、JDK2、XML序列化3、JSON序列化4、Hessian5、Avro序列化6、Kyro序列化7、Protostuff三、序列化框架對比測試1、對象準備2、JDK方式3、FastJson方式4、Hessian方式5、Protostuff方式6、測試代碼四、總結五、序列化應用場景六、注意事項一、簡介…

C++primer 第 2 章 變量和基本類型

2.1 基本內置類型 算術類型&#xff08;arithmetictype&#xff09;和空類型&#xff08;void&#xff09;在內的基本數據類型。其中算術類型包含了字符、整型數、布爾值和浮點數。空類型不對應具體的值&#xff0c;僅用于一些特殊的場合&#xff0c;例如最常見的是&#xff0…

codeforces 58A-C語言解題報告

58A題目網址 題目解析 1.輸入字符串,問如果刪去其中的一些自發,能否得到hello,如果能就輸出YES,否則輸出NO 舉例: 輸入: ahhellllloou 輸出: YES 2.注意點: 因為C語言沒有java中的匹配字符串,則新建立一個 word[6]“hello”; 在循環中使用word去與s匹配,當匹配到了就 count…

ClickHouse 客戶端命令

文章目錄一、簡介二、常用命令1、連接命令2、SQL語法&#xff08;1&#xff09;查看數據庫列表&#xff08;2&#xff09;查看當前使用的數據庫&#xff08;3&#xff09;查看數據庫中表列表&#xff08;4&#xff09;創建數據庫&#xff08;5&#xff09;創建表&#xff08;6&…

2000年考研英語閱讀理解文章三

文章詳細解析 注意點 1.當作者在文章中寫到:實際問題是:我們從根本上改變了嗎? 說明:我們沒有發生根本上的改變,作者不同意前文中的未來派詩歌 知識點 ----單詞 unhampered adj無阻礙的 finite adj有限的 ink n墨水 corresponding adj相應的,符合的 upsetting adj令人生厭…