前言
c++primer 第十一章学习心得
一、使用关联容器
map与set,前者的元素为键值对。根据容器类型、是否允许重复、是否有序分为8类
map | |
set | |
multimap | |
multiset | |
unordered_map | |
unordered_set | |
unordered_multimap | |
unordered_multiset |
二、关联容器概述
与顺序容器相比,关联容器不支持部分与位置相关的操作,例如push_back,也不支持构造函数接受一个值和一个数量值的操作。但关联容器由一些特定的操作,并且迭代器均为双向迭代器
1、定义关联容器
可以初始化为空,或者通过{}进行初始化
set<string> exclude = {"the","The","but","But"};
map<string,string> authors = {{"Joyce","Janmes"},{"Austen","Jane"}};
在有序容器中,关键字的类型必须是可比较的,默认使用<进行比较,也可以使用自己定义的比较方式。
2、pair
在map中,key与value是通过pair类型连接的,该类型定义在utility头文件中,可以通过first,second两个成员进行访问。
pair<int,int> p = {1,2};//自定义类型并初始化
auto p = make_pair(1,2);//使用make_pair自动推断类型
三、关联容器操作
额外类型:
类型名 | 特点 |
---|---|
key_type | 关键字类型 |
mapped_type | 仅用于map,值类型 |
value_type | set中与key_type相同,map中为pair<const key_type,const mapped_type>类型 |
使用迭代器时,解引用获得的是value_type类型的值引用,对map而言获得的是pair,需要通过成员first、second进行访问。对set的迭代器是const的,无法改变set中的元素。
因此对于关联容器,需要使用特定算法,例如find,或者特定的成员函数
1、添加元素
成员函数.insert(),可以添加一个元素或元素范围
map的插入需要插入pair元素,通常有四种方式:
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));
该成员函数具有返回值,对于不允许重复的容器类型为pair,first指向给定关键字的元素,second为bool类型,成功为ture。可重复的容器返回指向新元素的迭代器,无bool。
2、删除元素
除了通过迭代器删除某个或某个范围的元素,还支持对于特定关键字进行删除,返回值为删除的元素个数。对于不重复的容器,该值为0或1。
c.erase(key);
c.erase(iterator);
c.erase(beg,end);
3、map的下标操作
可以对于不重复的map使用类似vector的[]或者.at()访问元素,但需要注意的是,如果map中不存在该关键字,使用[key]时会自动进行值初始化并插入map中,使用.at()会抛出out_of_range异常,更加安全。
4、访问元素
.find(key)和.count(key)都可以获取指定元素,find返回迭代器,count返回出现的次数。
.lower_bound(k)返回不小于k的迭代器
.upper_bound(k)返回大于k的迭代器
.equal_range(k)返回的一个迭代器pair,first为起点,second为终点,若不存在,则指向可插入位置。
四、无序容器
由于维护元素的序成本较高,因此可以使用哈希函数和关键字比较“==”将不存在明显序关系的元素存储在无序容器中。同时,无序和有序可以相互转换,
无序容器在存储上是使用桶,每个桶保存0个或多个元素。通过哈希函数获得桶,在桶中使用顺序查找,因此需要对桶进行管理。
c.bucket_count()//当前桶数量
c.max_bucket_count()//容器最大桶数量
c.bucket_size(n)//第n个桶中元素数量
c.bucket(k)//k在哪个桶中
//哈希策略
c.load_factor()//每个桶平均数量,返回float
c.max_load_factor()//维护的平均数量,当load_factor值超过时会增加新桶
c.rehash(n)//重组,使桶数量大于n
c.reserve(n)//重组,使c可以保存n个元素且不必rehash
自定义类型使用无序容器时,需要提供哈希计算函数和==运算符