第10章 关联容器

       关联容器支持通过键来高效地查找和读取元素。基本关联容器:map和set。set仅包含一个键。multimap和multiset支持同一个键多次出现在容器中。

10.1、引言:pair类型

       pair类型,定义在utility头文件中。创建和初始化如:pair<T1,T2> p1(v1,v2);或make_pair(v1,v2)赋给pair类型的变量。

       对于pair类型,也可考虑typedef简化其声明:如,typedef pair<string,string> Author;

       对于pair类,可以直接访问其数据成员:其成员都是公有的。

10.3、map类型

       在使用关联容器时,它的键不但有一个类型,而且还有一个相关的比较函数。默认情况下,标准库使用键类型定义的<操作符来实现键的比较。对于键类型,唯一的约束就是必须支持<操作符

       map<K,V>::value_type是存储元素的键以及值的pair类型,而且键为const(但它的值成员可以修改)。key_type是键类型;mapped_type是值类型;

       用下标访问不存在的元素将导致在map容器中添加一个新的元素,它的键即为该下标值,如果没给该元素赋值,则值进行默认初始化,如int则初始化为0

       注:与vector和string类型不同,map下标操作符返回一个mapped_type类型的值,而map迭代器返回value_type类型的值,包含const key_type和mapped_type类型成员的pair对象。

10.3.5、map::insert的使用

       map<string,int>word;

       word["hello"]++;

       pair<string,int> word2("hello",33);

       word.insert(word2);//这边word2没有插入成功,wordhello值还是1。即在插入时,如果键在m中已经存在,则保持m不变。该函数返回一个pair类型对象,包含指向键为e.first的元素的map迭代器,以及一个bool类型的对象,表示是否插入了该元素,如:pair<map<string,int>::iterator, bool> ret=函数返回。++ret.first->second实现该值递增,->优先级高于++。

       还有如:insert(beg,end);beg和end是标记元素范围的迭代器,即插入该范围内的所有元素,遵循前闭后开原则。

10.3.6、查找并读取map中的元素

       m.count(k):返回m中k的出现次数。它对于map键来说,0,1可以反应一个键是否存在。

       m.find(k):如果m容器中存在按k索引的元素,则返回指向该元素的迭代器。如果不存在,则返回超出末端迭代器。如用:find函数!= 容器.end()来判断。

10.3.7、从map对象中删除元素

       map容器的erase操作返回void。而顺序容器的erase操作则返回一个迭代器,指向被删除元素后面的元素。

       m.erase(b,e)从m中删除一段范围内的元素,遵循前闭后开原则。

10.3.8、map对象的迭代遍历

       map同样提供begin和end运算。

10.4、set类型

       以一段范围的元素初始化set对象,或在set对象中插入一组元素时,对于每个键,事实上都只添加了一个元素。

       set中添加元素:(1)insert一个元素;(2)调用insert时,提供一对迭代器实参,插入其标记范围内所有的元素。

       set中获取元素:(1)find运算,找到返回对应元素的迭代器,否则为end()迭代器。(2)count运算,返回1或0。

       set的键也是const,不能通过找到的迭代器修改键值

10.5、multimap和multiset类型

       multimap不支持下标运算(显然,某个键对应多个值),其余与map操作相同。

10.5.1、元素的添加和删除

       带有一个参数的erase版本将删除拥有该键的所有元素,并返回删除元素的个数。而带有一个或一对迭代器参数的版本只删除指定的元素,并返回void类型

10.5.2、在multimap和multiset中查找元素

       在multimap中,同一个键所关联的元素必然相邻存放

       案例:假设有作者与书名映射,希望找到并输出某个作者写的所有书的书名。方法一,使用find和count操作。首先调用count确定某作者所写的书籍数目,然后调用find获得指向第一个该键所关联的元素迭代器。方法二,用lower_bound(k)(返回一个迭代器,指向键不小于k的第一个元素)和upper_bound(k)(返回一个迭代器,指向键大于k的第一个元素)。如果该键没有关联的元素,则lower_bound和upper_bound返回相同的迭代器,都指向同一个元素或同时指向multimap的超出末端位置。它们都指向在保持容器元素顺序的前提下,该键应被插入的位置。equal_range(k)返回一个迭代器的pair对象,它的first成员等价于m.lower_bound(k),second成员等价于m.upper_bound(k)。

10.6、容器的综合应用:文本查询程序

       设计程序的一个良好习惯是首先将程序所涉及的操作列出来。明确需要提供的操作,有助于建立需要的数据结构和实现这些行为。(看似常识,有时却不会去执行···)

       问题:查询给出的单词所在的行号及每行内容

       方法:(1)使用vector<string>类型的对象存储整个文件的副本,文件的每行是该对象的一个元素。在输出某一行时,只需以行号为下标获取该行所在的元素即可。(2)将每个单词所在的行号存储在一个set容器对象中。(3)使用一个map容器将 每个单词与一个 set 容器对象关联起来,该set容器对象记录此单词所在的行号。具体就是对每行的每个单词,用map[word].insert(行号);即可。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值