一、关联容器
map\multimap set\multiset 关联容器是通过红黑树来实现的。
1、关联容器的初始化
- 默认初始化
- 拷贝初始化(或者为一个容器的迭代器区间)
- 初始化列表初始化
2、关键字类型的要求
- 关键字类型定义一个“行为正常”的<运算符;
- 通过制定行为正常的comp函数:multiset<Sales_data, decltype(compareIsbn)*> bookstore(compareIsbn);
3、pair类型
定义在utility头文件中,含有first和second两个public数据成员
- 初始化
pair<T1,T2> p; //默认初始化
pair<T1,T2> p(v1,v2); pair<T1,T2> p = {v1,v2}; //用v1,v2分别初始化first和second成员
pair<T1,T2> p = make_pair(v1,v2); - p.first和p.second返回 p中第一个和第二个数据成员;即数据成员是public的
- 关系运算:先比较first,在first相等的情况下,再比较second,得出最终的关系
4、关联容器的操作
4.1 关联容器额外的类型别名
- key_type //关键字类型
- mapped_type //map专有,map中pair的second成员类型
- value_type //map的value_type是一个pair,我们可以改变pair的值但不能改变关键字成员的值;set的value_type就是key_type
- set的迭代器是const的。
- 我们通常不对关联容器使用泛型算法;在实际编程中,如果我们对一个关联容器使用算法,要么把它当做一个源序列,要么当做一个目的序列
- 关联容器支持begin和end;关联容器中的数据是按照关键字升序排列的
4.2 添加元素
- c.insert(v);
- c.emplace(args);
- c.insert(beg, end);
- c.insert(il);
- c.insert(p,v);
- c.emplace(p,v);
添加单一元素的insert和emplace返回一个pair;pair的first成员是一个迭代器,指向给定关键字的元素;second成员是一个bool,指出是否插入成功。
4.3 删除元素
- c.erase§; c.erase(b,e); //这是容器通用版本,返回删除元素后的位置
- c.erase(k); //k是key_type,返回删除的元素的数量
4.4 map的下标操作
返回类型是map_type的引用。
- 使用一个不在容器中关键字作为下标,会添加一个具有此关键字的元素到map中。
- c.at(k); //与顺序容器中的行为一致。
4.5 访问元素
lower_bound和upper_bound不适用于无序容器
- c.find(k); //返回一个迭代器,指向第一个关键字为k的元素
- c.count(k); //返回关键字为k的元素的数量
- c.lower_bound(k); //返回一个迭代器,指向第一个关键字不小于k的元素
- c.upper_bound(k); //返回一个迭代器,指向第一个关键字大于k的元素
- c.equal_bound(k); //返回一个迭代器pair,表示关键字等于k的集合
- lower_bound返回的迭代器可能指向一个具有给定关键字的元素,但也可能不指向。如果关键字不在容器中,则low_bound会返回关键字的第一个安全插入点——不影响容器中元素顺序的插入点。如果low_bound和upper_bound返回相同的迭代器,则给定关键字不在容器中。
二、无序容器
unordered_map\unordered_multimap unordered_set\unordered_multiset
1 如果关键字类型固有就是无序的,或者性能测试发现问题可以用哈希技术解决,就可以使用无序容器。
2 无序容器在存储上组织为一组桶,每个桶有零个或多个元素。无序容器使用一个哈希函数将元素映射到桶。也就是使桶的容量大于等于冲突元素的数量,一个桶可能容纳几个哈希值的元素
1、无序容器的管理操作
(1)、桶接口
- c.bucket_count(); //正在使用的桶的数目
- c.max_bucket_count(); //容器能容纳的最多的桶的数量
- c.bucket_size(n); //第n个桶中有多少个元素
- c.bucket(k); //关键字为k的元素在哪个桶中
(2)、桶迭代
- local_iterator //可以用来访问桶中元素的迭代器类型
- const_local_iterator //const版本
- c.begin(n),c.end(n);
- c.cbegin(n), c.cend(n); //返回桶n的首元素迭代器和尾后迭代器
(3)、哈希策略
- c.load_factor(); //每个桶平均元素数量,返回float值
- c.max_load_factor(); //c试图维护的平均桶大小,返回float值。c会在需要时添加新桶,以使得load_factor <= max_load_factor
- c.rehash(n); //重组存储,使得bucket_count >= n且bucket_count > size / max_load_factor
- c.reserve(n); //重组存储,使得c可以保存n个元素且不必rehash
2、无序容器对关键字类型的要求
- 无序容器使用关键字类型的==运算符来比较元素
- 使用一个 hash<key_type> 类型的对象来生成每一个元素的哈希值。
- 标准库为内置类型(包括指针)、string类型、智能指针类型提供了hash模板。
//定义Sales_data类型的哈希函数
size_t hasher(const Sales_data &sd)
{
return std::hash<std::string>()(sd.isbn());
}
//定义Sales_data类型的相等性判断运算符函数
bool eqOp(const Sales_data &lhs, const Sales_data &rhs)
{
return lhs.isbn() == rhs.isbn();
}
//无序容器类型要指明元素类型、哈希函数类型,相等性判定函数类型
using SD_multiset = std::unordered_multiset<Sales_data, decltype(hasher)*, decltype(eqOp)*>;
//无序容器的初始化,指明桶大小、哈希函数指针、相等性判定运算符指针
SD_multiset bookstore(42, hasher, eqOp);