这篇主要总结 关联式容器的使用以及底层结构
之前这篇总结的是 序列式容器,那么序列式容器和关联式容器有啥区别? 序列式容器的底层结构是线性序列的数据结构(数组、链表),而且序列式容器里面存储的是元素本身,但是 关联式容器存储的是键值对的形式,在数据检索的时候要比序列式容器效率高,因为其 底层结构大都是红黑树
关联式容器主要有哪些呢? 分为两种
- 树型结构 map,set ,multimap,multiset
- 哈希结构 unordered_map,unordered_set;
map
底层结构是红黑树,结构中的 key 数据有序,在 map 中是通过 key 进行排序和唯一标识元素的,value 存储的是与 key 关联的内容,支持下标访问,在 [key] 对应的值就是 value
map 的键值对构造的格式一般情况是 map<char,int>,但是也其他的格式,比如 <string,string> ,<int,int> 虽然都是可以的,但是在排序的时候,都是按照 key 的字典序的规则排序,也可以自己指定规则
基础操作
#include <map>
map<string, string> mp;
//m.insert(pair<string, string>("pear", "桃子"));
//m.insert(make_pair("banan", "香蕉"));
下面这种插入最常见的,也是最简单的方法。上面的两种插入方法了解即可
mp["pineapple"] = "菠萝";
mp["apple"] = "苹果";
mp["banana"] = "香蕉";
//查看 map 结构中的键值对,当我们插入进去的同时,
//底层结构的红黑树已经做了排序
//排序的方法就是根据 key 使用字典序规则
for (auto& e : m) {
cout << e.first << "---->" << e.second << endl;
// 排序的顺序是按照 key 字典序的方式 apple,banana,pineapple
}
//删除 key 值为 apple 的值
m.erase("apple");
operator [ ] 插入原理
用<key, T()>构造一个键值对,然后调用 insert() 函数将该键值对插入到 map 中;如果 key 已经存在,插入失败,insert 函数返回该 key 所在位置的迭代器;如果 key 不存在,插入成功,insert 函数返回新插入元素所在位置的迭代器;operator[ ] 函数最后将 insert 返回值键值对中的 value 返回
例如:将<“apple”, “”>插入 map 中,插入成功,返回 value 的引用,将“苹果”赋值给该引用结果,
在访问 value 的时候,我们有两种,前面使用 [ ] 进行访问。但是如果我们访问的 key 不存在 map 中,那么就会使用默认的 value 和 key 组成一个键值对插入,然后返回默认的 value ,一般情况下这个默认是空值。
另一种访问的方法是利用 at 函数,当访问的 key 不存在时,编译器会抛出一个异常,表示你访问的 key 不在 map 中。这也正是 at 和 [ ] 的区别。
所以如果我们查询的话,尽量使用 find 函数,而不要使用 []
multimap <int ,char>
底层结构也是红黑树,multimap 和