namespace bucket_hash
{
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)
{}
};
size_t GetNextPrime(size_t prime)
{
const int PRIMECOUNT = 28;
static const size_t primeList[PRIMECOUNT] =
{
53ul, 97ul, 193ul, 389ul, 769ul,
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
1610612741ul, 3221225473ul, 4294967291ul
};
size_t i = 0;
for (; i < PRIMECOUNT; ++i)
{
if (primeList[i] > prime)
return primeList[i];
}
return primeList[i];
}
template<class K, class V, class Hash = HashFunc<K>>
class HashTable
{
typedef HashNode<K, V> Node;
public:
// 拷贝 和 赋值 需要自己实现桶的拷贝
~HashTable()
{
for (size_t i = 0; i < _tables.size(); i++)
{
Node* cur = _tables[i];
while (cur)
{
Node* next = cur->_next;
delete cur;
cur = next;
}
_tables[i] = nullptr;
}
_n = 0;
}
bool Erase(const K& key)
{
if (_tables.size() == 0)
{
return false;
}
Hash hf;
// 素数
size_t index = hf(key) % _tables.size();
Node* prev = nullptr;
Node* cur = _tables[index];
while (cur)
{
if (cur->_kv.first == key)
{
// 1、cur是头结点
// 2、非头节点
if (prev == nullptr)
{
_tables[index] = cur->_next;
}
else
{
prev->_next = cur->_next;
}
delete cur;
--_n;
return true;
}
else
{
prev = cur;
cur = cur->_next;
}
}
return false;
}
Node* Find(const K& key)
{
if (_tables.size() == 0)
{
return nullptr;
}
Hash hf;
size_t index = hf(key) % _tables.size();
Node* cur = _tables[index];
while (cur)
{
if (cur->_kv.first == key)
{
return cur;
}
else
{
cur = cur->_next;
}
}
return nullptr;
}
bool Insert(const pair<K, V>& kv)
{
Hash hf;
//当负载因子到1时,进行扩容
if (_n == _tables.size())
{
//size_t newSize = _tables.size() == 0 ? 10 : _tables.size() * 2;
size_t newSize = GetNextPrime(_tables.size());
//HashTable newHT;
vector<Node*> newtables;
newtables.resize(newSize, nullptr);
for (size_t i = 0; i < _tables.size(); ++i)
{
Node* cur = _tables[i];
while (cur)
{
Node* next = cur->_next;
size_t index = hf(cur->_kv.first) % newSize;
cur->_next = newtables[index];
newtables[index] = cur;
cur = next;
}
_tables[i] = nullptr;
}
newtables.swap(_tables);
}
size_t index = hf(kv.first) % _tables.size();
Node* cur = _tables[index];
while (cur)
{
if (cur->_kv.first == kv.first)
{
return false;
}
else
{
cur = cur->_next;
}
}
Node* newnode = new Node(kv);
newnode->_next = _tables[index];
_tables[index] = newnode;
++_n;
return true;
}
private:
vector<Node*> _tables;
size_t _n = 0; // 存储多少有效数据
};
}
我们以KV模型的哈希表进行改造实现unordered_set和unordered_map:
template<class K, class T, class KeyOfT, class Hash = HashFunc<T> >
class HashBucket;
K:关键码类型
T: 不同容器T的类型不同,如果是unordered_map,T代表一个键值对,如果是unordered_set,T为 K
KeyOfT: 在哈希表中需要取到value,因为T的类型不同,通过value取key的方式就不同,详细见unordered_map/set的实现
Hash: 哈希函数仿函数对象类型,哈希函数使用除留余数法,如果是Key为string类型,需要将Key转换为整形数字才能取模
template<class T>
struct HashNode
{
T _data;
HashNode<T>* _next;
HashNode(const T& data)
:_data(data)
, _next(nullptr)
{}
};
如果是unordered_map,T代表一个键值对,如果是unordered_set,T为 K
哈希表的迭代器我们应该怎么实现呢?
哈希表的迭代器也是对节点指针进行了封装,我们想一想++操作怎么实现呢?一个桶遍历完了如何跳转到下一个桶?为了实现桶的跳转,我们在迭代器中还需要一个哈希表的指针
当下一个节点不为空时,++后的节点就在当前桶,返回即可,当下一个节点为空时,我们需要找下一个桶,首先通过当前节点计算找到当前节点所在桶的位置index,计算出后,++index即找到了下一个桶,当下一个桶存在时,如果下一个桶里面有数据(即不为空),则将第一个数据给当前节点,就实现了++,否则继续找下一个桶,当循环出来时,有可能是找到++后的节点了,也有可能说明走完了后面没有桶了,所以循环出来需要判断是不是没有桶了,没有桶则返回nullptr
Self operator++()
{
if (_node->_next) // 在当前桶迭代
{
_node = _node->_next;
}
else // 找下一个桶
{
KeyOfT kot;
const K& key = kot(_node->_data);
Hash hf;
size_t index = hf(key) % _ht->_tables.size();
++index;
_node = nullptr;
while (index < _ht->_tables.size())
{
if (_ht->_tables[index])
{
_node = _ht->_tables[index];
break;
}
else
{
++index;
}
}
// 后面没有桶了
if (index == _ht->_tables.size())
{
_node = nullptr;
}
}
return *this;
}
返回节点的数据的引用即可
T& operator*()
{
return _node->_data;
}
返回节点数据的地址即可
T* operator->()
{
return &_node->_data;
}
bool operator!=(const Self& s) const
{
return _node != s._node;
}
bool operator==(const Self& s) const
{
return _node == s._node;
}
// 前置声明
template<class K, class T, class KeyOfT,class Hash>
class HashTable;
template<class K, class T, class Hash, class KeyOfT>
struct HTIterator
{
typedef HashNode<T> Node;
typedef HashTable<K, T, Hash, KeyOfT> HT;
typedef HTIterator<K, T, Hash, KeyOfT> Self;
Node* _node;
HT* _ht;
HTIterator(Node* node, HT* ht)
:_node(node)
, _ht(ht)
{}
bool operator!=(const Self& s) const
{
return _node != s._node;
}
bool operator==(const Self& s) const
{
return _node == s._node;
}
T& operator*()
{
return _node->_data;
}
T* operator->()
{
return &_node->_data;
}
Self operator++()
{
if (_node->_next) // 在当前桶迭代
{
_node = _node->_next;
}
else // 找下一个桶
{
KeyOfT kot;
const K& key = kot(_node->_data);
Hash hf;
size_t index = hf(key) % _ht->_tables.size();
++index;
_node = nullptr;
while (index < _ht->_tables.size())
{
if (_ht->_tables[index])
{
_node = _ht->_tables[index];
break;
}
else
{
++index;
}
}
// 后面没有桶了
if (index == _ht->_tables.size())
{
_node = nullptr;
}
}
return *this;
}
};
然后在哈希表中实现迭代器的相关函数:
template<class K, class T, class KeyOfT, class Hash = HashFunc<K>>
class HashTable
{
typedef HashNode<T> Node;
friend struct HTIterator<K, T, Hash, KeyOfT>;//将迭代器设置成友元,让迭代器访问哈希表的私有
public:
typedef HTIterator<K, T, Hash, KeyOfT> iterator;
iterator begin()
{
for (size_t i = 0; i < _tables.size(); ++i)
{
if (_tables[i])
{
return iterator(_tables[i], this);
}
}
return end();//没有数据
}
iterator end()
{
return iterator(nullptr, this);
}
private:
vector<Node*> _table;
size_t _n = 0;
};
namespace bucket_hash
{
template<class T>
struct HashNode
{
T _data;
HashNode<T>* _next;
HashNode(const T& data)
:_data(data)
, _next(nullptr)
{}
};
size_t GetNextPrime(size_t prime)
{
const int PRIMECOUNT = 28;
static const size_t primeList[PRIMECOUNT] =
{
53ul, 97ul, 193ul, 389ul, 769ul,
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
1610612741ul, 3221225473ul, 4294967291ul
};
size_t i = 0;
for (; i < PRIMECOUNT; ++i)
{
if (primeList[i] > prime)
return primeList[i];
}
return primeList[i];
}
// 前置声明
template<class K, class T, class Hash, class KeyOfT>
class HashTable;
template<class K, class T, class Hash, class KeyOfT>
struct HTIterator
{
typedef HashNode<T> Node;
typedef HashTable<K, T, Hash, KeyOfT> HT;
typedef HTIterator<K, T, Hash, KeyOfT> Self;
Node* _node;
HT* _ht;
HTIterator(Node* node, HT* ht)
:_node(node)
, _ht(ht)
{}
bool operator!=(const Self& s) const
{
return _node != s._node;
}
T& operator*()
{
return _node->_data;
}
T* operator->()
{
return &_node->_data;
}
Self operator++()
{
if (_node->_next) // 在当前桶迭代
{
_node = _node->_next;
}
else // 找下一个桶
{
KeyOfT kot;
const K& key = kot(_node->_data);
Hash hf;
size_t index = hf(key) % _ht->_tables.size();
++index;
_node = nullptr;
while (index < _ht->_tables.size())
{
if (_ht->_tables[index])
{
_node = _ht->_tables[index];
break;
}
else
{
++index;
}
}
// 后面没有桶了
if (index == _ht->_tables.size())
{
_node = nullptr;
}
}
return *this;
}
};
template<class K, class T, class KeyOfT, class Hash = HashFunc<K>>
class HashTable
{
typedef HashNode<T> Node;
//template
friend struct HTIterator<K, T, Hash, KeyOfT>;
public:
typedef HTIterator<K, T, Hash, KeyOfT> iterator;
iterator begin()
{
for (size_t i = 0; i < _tables.size(); ++i)
{
if (_tables[i])
{
return iterator(_tables[i], this);
}
}
return end();
}
iterator end()
{
return iterator(nullptr, this);
}
// 拷贝 和 赋值 需要自己实现桶的拷贝
~HashTable()
{
for (size_t i = 0; i < _tables.size(); i++)
{
Node* cur = _tables[i];
while (cur)
{
Node* next = cur->_next;
delete cur;
cur = next;
}
_tables[i] = nullptr;
}
_n;
}
bool Erase(const K& key)
{
if (_tables.size() == 0)
{
return false;
}
Hash hf;
KeyOfT kot;
// 素数
size_t index = hf(key) % _tables.size();
Node* prev = nullptr;
Node* cur = _tables[index];
while (cur)
{
if (kot(cur->_data) == key)
{
// 1、cur是头结点
// 2、非头节点
if (prev == nullptr)
{
_tables[index] = cur->_next;
}
else
{
prev->_next = cur->_next;
}
delete cur;
--_n;
return true;
}
else
{
prev = cur;
cur = cur->_next;
}
}
return false;
}
Node* Find(const K& key)
{
if (_tables.size() == 0)
{
return nullptr;
}
Hash hf;
KeyOfT kot;
size_t index = hf(key) % _tables.size();
Node* cur = _tables[index];
while (cur)
{
if (kot(cur->_data) == key)
{
return cur;
}
else
{
cur = cur->_next;
}
}
return nullptr;
}
bool Insert(const T& data)
{
Hash hf;
KeyOfT kot;
//当负载因子到1时,进行扩容
if (_n == _tables.size())
{
//size_t newSize = _tables.size() == 0 ? 10 : _tables.size() * 2;
size_t newSize = GetNextPrime(_tables.size());
//HashTable newHT;
vector<Node*> newtables;
newtables.resize(newSize, nullptr);
for (size_t i = 0; i < _tables.size(); ++i)
{
Node* cur = _tables[i];
while (cur)
{
Node* next = cur->_next;
const K& key = kot(cur->_data);
size_t index = hf(key) % newSize;
cur->_next = newtables[index];
newtables[index] = cur;
cur = next;
}
_tables[i] = nullptr;
}
newtables.swap(_tables);
}
const K& key = kot(data);
size_t index = hf(key) % _tables.size();
Node* cur = _tables[index];
while (cur)
{
if (kot(cur->_data) == kot(data))
{
return false;
}
else
{
cur = cur->_next;
}
}
Node* newnode = new Node(data);
newnode->_next = _tables[index];
_tables[index] = newnode;
++_n;
return true;
}
private:
vector<Node*> _tables;
size_t _n = 0; // 存储多少有效数据
};
}
实现unordered_set只需要调用底层哈希表对应的接口即可:
#pragma once
#include "HashTable.h"
namespace Z
{
template<class K>
class unordered_set
{
struct SetKeyOfT
{
const K& operator()(const K& key) const
{
return key;
}
};
public:
typedef typename bucket_hash::HashTable<K, K,SetKeyOfT>::iterator iterator;
//没有实例化,没办法去哈希表中去找iterator,typename这就是告诉编译器这就是个类型,等实例化后再去找
iterator begin()
{
return _ht.begin();
}
iterator end()
{
return _ht.end();
}
//插入
pair<iterator,bool> insert(const pair<const K, V>& kv)
{
return _ht.Insert(kv);
}
//删除
bool erase(const K& key)
{
return _ht.Erase(key);
}
//查找
iterator find(const K& key)
{
return _ht.Find(key);
}
private:
bucket_hash::HashTable<K, K, SetKeyOfT> _ht;
};
实现unordered_map只需要调用底层哈希表对应的接口即可,和unordered_set不一样的是它需要实现[]运算符重载:
#pragma once
#include "HashTable.h"
namespace bit
{
template<class K, class V>
class unordered_map
{
struct MapKeyOfT
{
const K& operator()(const pair<const K, V>& kv) const
{
return kv.first;
}
};
public:
iterator begin()
{
return _ht.begin();
}
iterator end()
{
return _ht.end();
}
//插入
pair<iterator,bool> insert(const pair<const K, V>& kv)
{
return _ht.Insert(kv);
}
//[]运算符重载
V& operator[](const K& key)
{
pair<iterator,bool> ret = insert(make_pair(key,V()));
iterator it = ret.first;
return it->second;
}
//删除
bool erase(const K& key)
{
return _ht.Erase(key);
}
//查找
iterator find(const K& key)
{
return _ht.Find(key);
}
private:
bucket_hash::HashTable<K, pair<const K, V>, MapKeyOfT> _ht;
};
}