11.3 关联容器操作

  关联容器有三个额外的类型别名:key_type、mapped_type、value_type。

set<string>::value_type v1;  //v1是一个string
set<string>::key_type v2;  //v1是一个string
map<string, int>::value_type v3;  //v3是一个pair<const string,int>
map<string, int>::key_value v4;  //v4是一个string
map<string, int>::mapped_type v5;  //v5是一个int

关联容器迭代器

  当解引用一个关联容器迭代器时,我们会得到一个类型为容器value_type的值的引用。对map而言,value_type是一个pair类型,其first成员保存const的关键字,second成员保存值:

//获得指向word_count中一个元素的迭代器
auto map_it = word_count.begin();
//*map_it是指向一个pair<const string,size_t>对象的引用
cout << map_it->first;  //打印此元素的关键字
cout << " " << map_it->second;  //打印此元素的值
map_it->first = "new key";  //错误:关键字是const的
++map_it->second;  //正确:我们可以通过迭代器改变元素

  set的迭代器是const的
  虽然set类型同时定义了iterator和const_iterator类型,但两种类型都只允许只读访问set中的元素。

  遍历关联容器
  map和set都支持begin和end操作。我们可以用它们来进行遍历容器。

//获得一个指向首元素的迭代器
auto map_it = word_count.cbegin();
//比较当前迭代器和尾后迭代器
while (map_it != word_count.cend()) {
    //解引用迭代器,打印关键字-值对
    cout << map_it->first << " occurs"
        << map_it->second << " times" << endl;
    ++map_it;  //递增迭代器,移动到下一个元素
}

  关联容器和算法
  我们通常不对关联容器使用泛型算法,关键字是const这一特性意味着不能将关联容器传递给修改或重排容器元素的算法。在实际编程中,如果我们真要对一个关联容器使用算法,要么是将它作一个源序列,要么当作一个目的位置。

添加元素

  关联容器的insert成员向容器中添加一个元素或一个元素范围。由于map和set包含不重复的关键字,因此插入一个已存在的元素对容器没有任何影响:

vector<int> ivec = { 2,4,6,8,2,4,6,8 };  //ivec有8个元素
set<int> set2;  //空集合
set2.insert(ivec.cbegin(), ivec.cend());  //set2有4个元素
set2.insert({ 1,3,5,7,1,3,5,7 });  //set2现在有8个元素

  insert有两个版本,分别接受一对迭代器,或是一个初始化器列表。

  向map添加元素
  对一个map进行insert操作时,必须记住元素类型是pair。

//向word_count插入word的4种方法
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));

  检测insert的返回值
  insert的返回值依赖于容器类型和参数。对于不包含重复关键字的容器,添加单一元素的insert和emplace版本返回一个pair,pair的first成员是一个迭代器,指向具有给定关键字的元素;second成员是一个bool值,指出元素是插入成功还是已经存在于容器中。

  向multiset和multimap添加元素
  由于multi容器中的关键字不必唯一,在这些类型上调用insert总会插入一个元素:

multimap<string, string> authors;
//插入第一个元素。关键字为Barth,John
authors.insert({ "Barth,John","Sot-Weed Factor" });
//正确:添加第二个元素,关键字也是Barth,John
authors.insert({ "Barth,John","Lost in the Funhouse" });

删除元素

  关联容器定义了三个版本的erase,与顺序容器一样,我们可以通过传递给erase一个迭代器或一对迭代器来删除一个元素或者一个元素范围。关联容器还提供一个额外的erase操作,它接受一个key_type参数。此版本删除所有匹配给定关键字的元素,返回实际删除的元素的数量:

//删除一个关键字,返回删除的元素数量
if (word_count.erase(removal_word))
cout << "ok: " << removal_word << " removed\n";
else cout << "oops: " << removal_word << " not found!\n";

map的下标操作

  map和unordered_map容器提供了下标运算符和一个对应的at函数。set类型不支持下标。

map<string, size_t> word_count;  //empty map
//插入一个关键字为Anna的元素,关联值进行值初始化,然后将1赋予它
word_count["Anna"] = 1;

  使用下标运算符可能插入一个新元素,我们只可以对非const的map使用下标操作。

  使用下标操作的返回值
  map的下标元素符与我们用过的其他下标运算符的另一个不同之处是其返回类型。当对一个map进行下标操作时,会获得一个mapped_type对象;但当解引用一个map迭代器时,会得到一个value_type对象。如果关键字还未在map中,下标运算符会添加一个新元素。

访问元素

  关联容器提供多种查找一个指定元素的方法,例如find和count。

set<int> iset = { 0,1,2,3,4,5,6,7,8,9 };
iset.find(1);  //返回一个迭代器。指向key==1的元素
iset.find(11);  //返回一个迭代器,其值等于iset.end()
iset.count(1);  //返回1
iset.count(11);  //返回0

  在multimap和multiset中查找元素
  在容器中可能有很多元素具有给定的关键字,如果一个multimap和multiset中有多个元素具有给定关键字,则这些元素在容器中会相邻存储。。

string search_item("Alain de Botton");  //要查找的作者
auto entries = authors.count(search_item);  //元素的数量
auto iter = authors.find(search_item);  //此作者的第一本书
//用一个循环查找此作者的所有著作
while (entries) {
    cout << iter->second << endl;  //打印每个题目
    ++iter;   //前进到下一本书
    --entries;  //记录已经打印了 多少本书
}

  一种不同的,面向迭代器的解决方法
  我们还可以用lower_bound和upper_bound来解决此问题。这两个操作接受一个关键字,返回一个迭代器。如果关键字在容器中,lower_bound返回迭代器将指向第一个具有给定关键字的元素,而upper_bound返回的迭代器则指向最后一个匹配给定关键字的元素之后的位置。如果不在multimap中,则lower_bound和upper_bound会返回相等的迭代器,指向一个不影响排序的关键字插入位置。

 //authors和search_item的定义。与前面的程序一样
//beg和end表示对应此作者的元素的范围
for (auto beg = authors.lower_bound(search_item),
    end = authors.upper_bround(search_item);
    beg != end; ++beg)
    cout << beg->second << endl;  //打印每个题目

  equa_range函数
  解决此问题的最后一种方法是三种方法中最直接的:直接调用equal_range即可。此函数接受一个关键字,返回一个迭代器pair。若关键字存在,则第一个迭代器指向第一个与关键字匹配的元素,第二个迭代器指向最后一个匹配元素的位置,若未找到元素,则两个迭代器都指向关键字可以插入的位置。

//authors和search_item的定义。与前面的程序一样
//pos保存迭代器对,v表示与关键字匹配的元素范围
for (auto pos = authors.equal_range(search_item);
    pos.first != pos.second; ++pos.first)
    cout << pos.first->second << endl;  //打印每个题目
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容

  • 1. 使用关联容器 2. 关联容器概述2.1 定义关联容器2.2 关键字类型的要求2.3 pair类型 3. 关联...
    MrDecoder阅读 473评论 0 0
  • 关联容器和顺序容器根本的不同: 关联容器中的元素是按关键字保存和访问的;顺序容器中的元素是按在容器中的位置顺序保存...
    Kreat阅读 193评论 0 0
  • 第11章 关联容器 关联容器类型描述map保存关键字-值对multimap关键字可重复的mapset保存关键字mu...
    北冥有鱼wyh阅读 369评论 0 1
  • 简介 标准库提供8个关联容器: map:关联数组 set:只保存关键字 multimap:关键字可重复出现的map...
    TOMOCAT阅读 244评论 0 0
  • 关联容器 关联容器支持高效的关键字查找和访问,两个主要的关联容器是map和set,map中的元素是一些关键字-值(...
    土豆吞噬者阅读 367评论 0 0