C++ 用哈希表封装unordered_set/map
文章目录
- 一、unordered_set/map基本框架
- 二、插入、删除、查找
- 三、迭代器
- 四、map支持[]
- 五、完整代码
一、unordered_set/map基本框架
1.unordered_set/map的底层是一个哈希桶,并且unordered_set/map底层共用一个哈希桶
但是unordered_set是一个key场景,unordered_map是一个key/value场unordered_set
底层需要存储一个key,unordered_map底层需要存储一个key和一个value,存储数据的个
数都是不相等的,那么如何实现呢?在底层的哈希桶当中可以设置为只存储一个数据的
哈希桶,对于unordered_set那么只需要传一个key过去就可以,此时哈希桶底层存储的
是一个数据key,那么对于unordered_map传一个pair<key,value>就可以,那么此时底层
哈希桶当中存储的就是一个pair<key,value>实现了unordered_set/map底层共用一个哈桶
2.unordered_set/map共用一个哈希桶,哈希桶只存储一个数据,但是对于
unordered_set/map在进行插入删除查找时都是根据key的逻辑去实现,但是此时哈希桶
只知道存储一个数据,该数据可能直接就是key,也就有可能是一个pair需要取出它的成员
first,虽然哈希桶不知道数据是哪种,但是unordered_set/map封装哈希桶的上层是知道存
储什么样的数据的,所以只需要在unordered_set/map封装哈希桶时传递一个可调用对象
该可调用对象可以将其中的key提取出来,那么在底层的哈希桶当中就使用该仿函数提取出
key再进行剩下操作
3.在我们外层使用时,我们是直接使用unordered_set/map的模板以及接口,那么就表明
对于哈希桶所需要的将key转为整型的可调用对象以及比较相等的可调用对象的缺省值
需要在unordered_set/map这一层进行传递
4.由于查找删除时参数只需要传递key,那么就需要key的类型,由于 unordered_set/map
一个是key一个是pair<key,value>,底层的哈希桶是不清楚是哪种类型的,所以在实现哈希桶
时需要额外的传递一个key的类型
5.改良后的哈希桶
6.unordered_set/map框架
二、插入、删除、查找
1.插入、删除、查找直接对底层的哈希桶的插入进行封装即可
2.在后续实现迭代器时,就需要将插入的返回值变换为返回一个piar<iterator,bool>
这样可以为后续的map重载运算符[]制造前提,包括find的返回值应该返回查找到的
数据的迭代器
3.代码
三、迭代器
1.哈希桶的迭代器也是通过封装哈希桶底层的结点的指针,来实现*是当前迭代器所指代的
结点中的数据,->是当前迭代器所指代的结点中的结构体的成员,++是下一个结点的
迭代器,使得迭代器实现指针的行为
2.哈希桶的迭代器是一个单向迭代器,因为哈希桶底层存储的链表是一个单链表
3.哈希桶的迭代器除了++其余都跟封装链表结点的指针一样,但是对于++,++迭代器
是下一个结点的迭代器,那么如果当前桶中的链表结点拥有下一个结点,那么直接返回
当前结点的下一个结点的迭代器即可,但是如果当前桶中的链表结点没有下一个结点
那么就需要去找到下一个拥有有效数据的桶,将该桶的链表中第一个结点的迭代器进行返回
但是哈希桶中的链表是一个单向链表,不能往回走,那么为了面对这种情况,为了可以当
当前桶走完后到达下一个桶,哈希桶的迭代器中还会存储哈希桶的指针,那么迭代器中
拥有哈希桶的指针,那么就可以通过当前迭代器计算出此时在哈希桶中的位置,然后
通过哈希桶指针找到哈希桶在锁定到当前迭代器当中的具体桶的位置去寻找下一个桶
4.当底层的哈希桶的迭代器实现完毕过后,上层的unordered_sety/map对哈希桶的迭代器
进行封装即可
5.begin()和end()
5.1begin()返回哈希桶当中的第一个有效数据的结点的迭代器,那么就需要找到哈希桶
中的第一个有效桶,然后将有效桶当中的第一个结点的迭代器返回
5.2end()返回的迭代器底层为nullptr就可以表示最后一个有效数据的下一个位置
6.哈希桶迭代器代码
7.unordered_set/map封装哈希桶迭代器
四、map支持[]
1.首先将哈希桶的插入接口的返回值修改为返回pair<iterator,bool>
以及find接口返回值改为返回迭代器,然后再将外层unordered_set/map
的inset和find接口的返回值改成对应的类型
2.此时在map中实现[]运算符重载直接复用insert即可,此时原本就在哈希桶存储的
数据insert返回的pair<iterator,bool>中会有该数据的迭代器,如果不在哈希桶当中
那么就会将该数据进行插入{key,value()},然后返回的pair<iterator,bool>中会有
新插入的数据的迭代器,此时就可以通过key找到value或者是插入新的key然后获取到
value
五、完整代码
1.unordered_set
2.unordered_map
3.哈希桶