第十一章 关联容器 400

两个主要的关联容器:map、set
map中的元素是 关键字—值 对
set中只有关键字
标准库提供8个关联容器,8个容器的不同体现在三个方面:
(1)是map 还是 set
(2)要求不重复关键字 还是 不允许重复关键字——容器名前加multi
(3)有序 还是 无序——容器名前加unordered
在这里插入图片描述
11-1使用关联容器
使用map
map类型通常通常被称为关联数组
单词计数程序:
在这里插入图片描述
定义map必须指定关键字和值得类型
string作为下标,每读取一个word,如果word还未在map中,下标运算符会创建一个新元素,其关键字为word,值为0。
不管元素是否是新创建的,我们将其值加一
当从map中提取一个元素时,会得到一个pair类型的对象。pair是一个模板类型,保存两个名为first和second的数据成员
map所使用的pair用first成员保存关键字,用second成员保存对应的值
使用set
忽略常见的单词,只对不在忽略集合的单词计数:
在这里插入图片描述
定义set必须指定其元素类型
在这里插入图片描述
如果关键字在set中,find返回的迭代器指向该关键字,如果不在,则返回尾后迭代器
11-2关联容器概述
关联容器都支持普通容器操作,但不支持顺序容器的相关位置的操作,例如push front、push back,因为关联容器中的元素时根据关键字存储的,这些操作对关联容器无用。关联容器也不支持构造函数或插入操作这些接受一个元素和一个数量值得操作
1、定义关联容器
每个关联容器都都有一个默认构造函数,它创建一个指定类型的空容器
可以将关联容器初始化为另一个同类型容器的拷贝,或从值范围来初始化关联容器,只要这些值可以转化为容器所需类型就可以
对关联容器进行值初始化:
在这里插入图片描述
初始化multimap或multiset
用含有20个元素的vector来初始化multiset和set:
在这里插入图片描述
初始化后miset有20个元素,set只有10个
2、关键字类型的要求
默认情况下,标准库使用关键字类型的<运算符来比较两个关键字
在集合类型中,关键字类型就是元素类型
在映射类型中,关键字类型是元素的第一部分的类型
有序容器的关键字类型
我们可以提供自己定义的操作来代替关键字上的<运算符,所提供的操作必须在关键字类型上定义一个严格弱序,可以将严格弱序看做“小于等于”
比较函数必须具备如下性质:
在这里插入图片描述
如果两个关键字等价,则关键字视作它们相等
当用作map的关键字时,只能有一个元素与这两个关键字关联,可以用两者的任意一个来访问其值
使用关键字类型的比较函数
自定义的操作类型必须紧跟在容器定义的尖括号之后
不能直接定义一个Sales_data的multiset,因为Sales_data的没有<运算符,定义一个compareIsbn来代替其功能:
在这里插入图片描述
在定义multiset时必须提供两个类型:关键字类型——Sales_data,比较操作类型——指向compareIsbn的函数指针类型
在这里插入图片描述
3、pair类型
pair类型定义在头文件utility中
pair是一个用来生成特定类型的模板,它保存两个数据成员。创建pair时,必须提供两个类型名,两个类型不要求一样
例如:
在这里插入图片描述
pair的默认构造函数对数据成员进行值初始化:anon保存两个空string、word count保存一个空string和0、line保存一个空string和空vector
也可以为每个成员提供初始化器:
在这里插入图片描述
标准库定义的pair操作:
在这里插入图片描述
创建pair对象的函数
如果需要一个函数返回pair,可以对返回值进行列表初始化:
在这里插入图片描述
在这里插入图片描述
若v不为空,则返回由v中最后一个string和这个string的大小构成的pair;否则返回一个空pair
显式构造返回值:
在这里插入图片描述
用make_pair生成pair对象:
在这里插入图片描述
pair的两个类型来自于make_pair的两个参数
11-3关联容器操作
容器关键字和值得类型:
在这里插入图片描述
在一个map中,每一个元素是一个pair对象,包含一个关键字和一个关联的值。元素的关键字是不能改变的,所以这些pair的关键字部分是const的
在这里插入图片描述
只有map类型才定义了mapped_type类型
1、关联容器迭代器
当解引用一个关联容器迭代器时,我们会得到一个类型为容器的value type的值得引用
map的迭代器:
在这里插入图片描述
set的迭代器是const的
虽然set类型同时定义了iterator和const_iterator,但两种类型都只允许只读set中的元素
set中的关键字也是const的:
在这里插入图片描述
历遍关联容器
打印单词计数程序的结果:
在这里插入图片描述
关联容器和算法
关联容器可用于只读元素的算法,但很多算法都要搜索序列,不能快速地通过关键字进行查找:泛型find算法进行顺序搜索查找一个元素,而关联容器定义的专用的find成员比它快得多在这里插入图片描述
2、添加元素
关联容器的insert成员向容器中添加一个元素或范围内的元素
由于map和set不包含重复的关键字,所有插入一个已存在的元素对容器没有任何影响
在这里插入图片描述
向map添加元素
对map进行insert操作时,必须记住元素类型是pair
在这里插入图片描述
在这里插入图片描述
检测insert的返回值
对于不包含重复关键字的容器,添加单一元素的insert(或emplace)版本返回一个pair
pair的first成员是一个迭代器,指向插入的元素
second成员是一个bool值,指出元素是插入成功还是已存在:如果已存在,则bool的值为false,insert什么也不做;如果不存在,则元素被插入,bool的值为true
重写单词计数程序:
在这里插入图片描述
递增语句在这里插入图片描述的解释:
在这里插入图片描述
旧版的ret的声明和初始化:
在这里插入图片描述
向multimap和multiset添加元素
建立作者和他的作品的映射:
在这里插入图片描述
对于允许关键字重复的容器,接受党元素的insert返回指向插入元素的迭代器,无须返回bool值
3、删除元素
关联容器定义了三个版本的erase:
接受一个迭代器的版本——删除一个元素,返回void
接受一对迭代器的版本——删除范围内元素,返回void
接受一个key_type参数,返回删除元素的数量
从word count中删除removal word:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
4、map的下标操作
map和unordered_map提供了下标运算符和一个对应的at函数
set类型不支持下标,set的元素本身就是关键字,没有与关键字关联的值,下标操作无意义
不能对multimap或unordered_multimap进行下标操作,因为可能删除多个值
map下标运算符接受一个索引(关键字),并获得与其关联的值,如果这个关键字不存在,则会创建一个元素并插入到map中,将其值进行值初始化
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
使用下标操作的返回值
通常情况下,解引用迭代器和使用下标运算符返回的结果的类型是一样的
但对map进行下标操作只返回值,解引用其迭代器会得到value_type对象
map的下标运算返回左值,所有既可以读也可以写元素:
在这里插入图片描述
5、访问元素
对于不允许关键字重复的容器,使用find和count可能没有什么区别
对于允许关键字重复的容器,count会做更多工作:返回重复元素的个数
例如:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
对map使用find代替下标操作
下标操作可能会创建一个新的元素,导致改变map
如果只希望查找值,而不想改变map,应该使用find:
在这里插入图片描述
在multimap或multiset中查找元素
在允许重复关键字的容器中,具有相同关键字的元素会相邻存储
使用find和count打印一个作者的所有著作:
在这里插入图片描述
lower_bound和upper_bound
lower_bound和upper_bound都返回一个迭代器,lower_bound返回的迭代器指向第一个具有给定关键字的元素,upper_bound返回的迭代器指向最后一个具有给定关键字的元素之后的位置
如果元素不存在,lower_bound和upper_bound会返回相等的迭代器——指向一个不影响排序的关键字的位置
用相同的关键字调用lower_bound和upper_bound会得到一个迭代器范围
例如:
在这里插入图片描述
equal_range函数
equal_range函数接受一个关键字,返回一个迭代器pair,如果关键字存在,则第一个迭代器指向第一个与给定关键字匹配的元素,第二个迭代器指向最后一个与给定关键字匹配的元素之后的位置;如果未找到匹配元素,则两个迭代器指向关键字可以插入的位置
在这里插入图片描述
6、一个单词转换的map
程序功能:将一个给定的string转换为另一个string
程序的输入:一个保存规则的文件,一个需要转换的文本文件
规则由两部分组成:简写的单词和与之对应的短语
单词转换程序
word_transform接受两个ifstream参数:第一个参数绑定到单词转换文件,第二个参数绑定到我们要转换的文本文件
buildMap函数读取转换规则文件 ,并创建一个map,用于保存每个单词到其转换内容的映射
transform函数接受一个string返回转换后的内容
定义word_transform函数
在这里插入图片描述
建立转换映射
定义buildMap读入给定文件,建立转换映射:
在这里插入图片描述
生成转换文本
定义transform函数:
在这里插入图片描述
11-4无序容器
无序关联容器不是使用比较运算符来组织元素,而是使用一个哈希函数和关键字类型的运算符
使用无序容器
通常可以用一个无序容器替换对应的有序容器,反之亦然
用unordered_map重写单词计数程序:
在这里插入图片描述
单词不太可能按字典顺序输出
管理桶
无序容器在存储上组织为一组桶,每个桶保存0个或多个元素
无序容器使用哈希函数将元素映射到桶
容器将具有一个特定哈希值得所有元素保存在相同的桶中
如果容器允许重复关键字,则相同关键字的元素也都在同一个桶中
在这里插入图片描述
无序容器对关键字类型的要求
默认情况下,无序容器使用
运算符来比较元素,它们还使用一个hash<key_type>类型的对象来生成每个元素的哈希值
我们可以直接定义关键字是内置类型、string、智能指针类型的无序容器
不能直接定义关键字类型为自定义类类型的无序容器
为了将Sales_data用作关键字,我们要提供函数来代替==运算符和哈希值计算函数
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值