👀樊梓慕:个人主页
🎥个人专栏:《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C++》《Linux》《算法》
🌝每一个不曾起舞的日子,都是对生命的辜负
目录
前言
上次我们模拟实现了闭散列的哈希表与开散列的哈希表,但很明显上次实现的很粗糙功能很简单,迭代器并没有实现,以及泛型编程思想也没有应用,那么对于本篇文章我们要用一个哈希表同时封装出unordered_set 与 unordered_map,对此我们之前已经成功用一颗红黑树同时封装出set与map,大致的思想是类似的,只不过这里会略微复杂一些。
欢迎大家📂收藏📂以便未来做题时可以快速找到思路,巧妙的方法可以事半功倍。
=========================================================================
GITEE相关代码:🌟樊飞 (fanfei_c) - Gitee.com🌟
=========================================================================
1.哈希桶源码
//每个哈希桶中存储数据的结构
template<class K, class V>
struct HashNode
{
pair<K, V> _kv;
HashNode<K, V>* _next;
//构造函数
HashNode(const pair<K, V>& kv)
:_kv(kv)
, _next(nullptr)
{}
};
//哈希表
template<class K, class V>
class HashTable
{
public:
typedef HashNode<K, V> Node;
//插入函数
bool Insert(const pair<K, V>& kv)
{
//1、查看哈希表中是否存在该键值的键值对
if (Find(kv.first)) //哈希表中已经存在该键值的键值对(不允许数据冗余)
{
return false; //插入失败
}
//2、判断是否需要调整哈希表的大小
if (_n == _tables.size()) //负载因子超过1
{
//增容
//a、创建一个新的哈希表,新哈希表的大小设置为原哈希表的2倍
vector<Node*> newTables(_tables.size() * 2, nullptr);
//b、将原哈希表当中的结点插入到新哈希表
for (size_t i = 0; i < _tables.size(); i++)
{
//取出旧表中的节点,重新计算挂到新表桶中
Node* cur = _tables[i];
while (cur)
{
Node* next = cur->_next;
size_t hashi = cur->_kv.first % newTables.size();
//将该结点头插到新哈希表中编号为index的哈希桶中
cur->_next = newTables[hashi];
newTables[hashi] = cur;
cur = next;
}
_tables[i] = nullptr; //该桶取完后将该桶置空
}
//c、交换这两个哈希表
_tables.swap(newTables);
}
//3、将键值对插入哈希表
size_t hashi = kv.first % _tables.size(); //通过哈希函数计算出对应的哈希桶编号index(除数不能是capacity)
Node* newnode = new Node(kv); //根据所给数据创建一个待插入结点
//将该结点头插到新哈希表中编号为index的哈希桶中
newnode->_next = _tables[hashi];
_tables[hashi] = newnode;
//4、哈希表中的有效元素个数加一
_n++;
return true;
}
//查找函数
HashNode<K, V>* Find(const K&am