1. 哈希封装思路
首先,内层用的是哈希表,哈希表使用泛型编程,外层unordered_map和unordered_set给与相应的参数,之后编译器自动生成。
2. 哈希封装的模拟实现
主要由三个头文件进行封装,My_unordered_map.h,My_unordered_set.h和HashTable.h头文件,分别装有My_unordered_map,My_unordered_set,哈希表。
2.1 HashTable.h
除留取余法的仿函数,让数据类型转换为可以取余的类型
template<class K>
struct HashFunc
{
size_t operator()(const K& key)
{
return (size_t)key;
}
};
// 特化
template<>
struct HashFunc<string>
{
// abcd
// bcad
// aadd
// BKDR
size_t operator()(const string& key)
{
size_t hash = 0;
for (auto ch : key)
{
hash *= 131;
hash += ch;
}
return hash;
}
};
2.1.1 节点数据类
用来初始化节点,定义节点数据
// 节点数据
template<class T>
struct HashNode
{
T _data;// 节点数据
HashNode<T>* _next;// 下一个节点地址
// 构造函数
HashNode(const T& data)
:_data(data),
_next(nullptr)
{
}
};
2.1.2 迭代器类
operator++()
节点是这个表索引位置下的最后一个节点
a.找下一个不为空的数组索引的指针,找到
b.没找到,直接置空
节点不是表索引的位置下的最后一个节点,直接找下一个节点
// ++
// 如果当前节点是这个表的_tables[i]的最后一个节点,++需要找到数组的下一个索引
// 所以需要引入表,才可以找到下一个位置
// 1.节点是这个表索引位置下的最后一个节点
// a.找下一个不为空的数组索引的指针,找到
// b.没找到,直接置空
// 2.节点不是表索引的位置下的最后一个节点,直接找下一个节点
Self& operator++()
{
// 2.节点不是表索引的位置下的最后一个节点,直接找下一个节点
if (_node->_next)
{
_node = _node->_next;
}
else// 1.节点是这个表索引位置下的最后一个节点
{
Hash hs;
KeyOfT kot;
// 首先找到这个表上当前节点的索引位置
size_t i = hs(kot(_node->_data)) % _pht->_tables.size();
++i;
// 寻找这个表上下一个指向不为空的索引下的指针
for (; i < _pht->_tables.size(); i++)
{
// 如果不为空,则就找到了
if (_pht->_tables[i])
{
break;
}
}
// 如果遍历完表也没找到指向不为空的索引指针
if (i == _pht->_tables.size())
{
_node = nullptr;
}
else
{
_node = _pht->_tables[i];// _node指向这个索引位置下指针指向的第一个节点
}
}
return *this;
}
由于如果当前节点是当前索引的最后一个节点时,则要找下一个指向不为空的索引指针,所以要获取当前表。所以成员会引入
const HashTable<K, T, KeyOfT, Hash> _pht;// 引用一个表的指针*
但是哈希表中也会引入迭代器,所以两两形式互相依赖,所以需要在迭代器类的前面进行哈希表类的声明
// 由于__HTIterator类和HashTable互相依赖,__HTIterator中引入表的成员变量,HashTable也引入了迭代器
// 两两互相依赖
// 由于__HTIterator先定义的,得HashTable类在前面声明,否则无法找到HashTable
template<class K, class T, class KeyOfT, class Hash>
class HashTable;
迭代器类的总体代码
// 哈希桶的迭代器
// data T& T*
template<class K,class T, class KeyOfT, class Hash, class Ref, class Ptr>
struct __HTIterator
{
public:
// 重定义节点数据
typedef HashNode<T> Node;
// 重定义迭代器数据
typedef __HTIterator<K, T, KeyOfT, Hash, Ref,Ptr> Self;
// 构造函数
__HTIterator(Node* node, const HashTable<K, T, KeyOfT, Hash>* pht)
:_node(node),
_pht(pht)
{
}
// 解引用
// T&
Ref operator*()
{
return _node->_data;
}
// 解引用
// T*
Ptr operator->(</