目录
前言
封装迭代器
改良后的HashTable.h
unordered_set模拟实现代码
unordered_map模拟实现代码
unordered_map、unordered_set与map、set的区别是unoedered系列无序,除此之外功能上没有区别。但二者之间底层不同,前者底层为哈希,后者为红黑树。
unoedered系列,并没有反向迭代器,同时通过观察源码,发现这次的const迭代器并没有复用非const迭代器:
哈希表的迭代器与其他容器的迭代器有所不同,哈希表的迭代器增加了一个 HashTable 的指针,不增加这个变量是无法完成哈希表的迭代器的,这也意味着 const 版本的迭代器需要重新写在另一个类,不能复用普通迭代器的代码完成const 迭代器
// 前置声明
template
class HashTable;
template
struct __HashTableIterator
{
typedef HashNode Node;
typedef __HashTableIterator self;
typedef HashTable HT; // HashTable在这段代码下面,他找不到,报错
Node* _node;
HT* _pht; // HashTable的指针
__HashTableIterator(Node* node, HT* pht)
:_node(node)
,_pht(pht)
{}
T& operator* () {
return _node->_data;
}
T* operator->() {
return &_node->_data;
}
// 前置++
self operator++() {
if (_node->_next) {
_node = _node->_next;
}
else {
// 如果一个桶走完了,找到下一个桶继续遍历
KeyOfT koft;
size_t i = _pht->HashFunc(koft(_node->_data)) % _pht->_tables.size();
++i;
for (i; i < _pht->_tables.size(); i++) {
Node* cur = _pht->_tables[i];
if (cur) {
_node = cur;
return* this;
}
}
_node = nullptr;
}
return* this;
}
bool operator!=(const self& s) {
return _node != s._node;
}
};
namespace OPEN_HASH2
{
// 开散列-哈希桶
template
struct HashNode
{
T _data;
HashNode* _next;
HashNode(const T& data)
:_data(data)
,_next(nullptr)
{}
};
// 前置声明
template
class HashTable;
template
struct __HashTableIterator
{
typedef HashNode Node;
typedef __HashTableIterator self;
typedef HashTable HT; // HashTable在这段代码下面,他找不到,报错
Node* _node;
HT* _pht; // HashTable的指针
__HashTableIterator(Node* node, HT* pht)
:_node(node)
,_pht(pht)
{}
T& operator* () {
return _node->_data;
}
T* operator->() {
return &_node->_data;
}
// 前置++
self operator++() {
if (_node->_next) {
_node = _node->_next;
}
else {
// 如果一个桶走完了,找到下一个桶继续遍历
KeyOfT koft;
size_t i = _pht->HashFunc(koft(_node->_data)) % _pht->_tables.size();
++i;
for (i; i < _pht->_tables.size(); i++) {
Node* cur = _pht->_tables[i];
if (cur) {
_node = cur;
return* this;
}
}
_node = nullptr;
}
return* this;
}
bool operator!=(const self& s) {
return _node != s._node;
}
};
template
struct _Hash
{
const K operator()(const K& key) {
return key;
}
};
//特化
template<>
struct _Hash
{
size_t operator()(const string& key) {
// BKDR Hash
// https://www.cnblogs.com/-clq/archive/2012/05/31/2528153.html
size_t hash = 0;
for (size_t i = 0; i < key.size(); i++)
{
hash *= 131;//
hash += key[i];
}
return hash;
}
};
//struct _Hashstring
//{
// size_t operator()(const string& key) {
// // BKDR Hash
// // https://www.cnblogs.com/-clq/archive/2012/05/31/2528153.html
// size_t hash = 0;
// for (size_t i = 0 ; i < key.size(); i++)
// {
// hash *= 131;//
// hash += key[i];
// }
// return hash;
// }
//};
template
class HashTable
{
typedef HashNode Node;
public:
friend struct __HashTableIterator;
typedef __HashTableIterator 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()
{
Clear();
}
void Clear() {
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;
}
}
size_t HashFunc(const K& key) {
Hash hash;
size_t index = hash(key);
return index;
}
pair Insert(const T& data)
{
KeyOfT koft;
// 如果负载因子等于1,则增容,避免大量的哈希冲突
// 负载因子=表中数据/表的太小 衡量哈希表满的程度
if (_tables.size() == _num)
{
// 1、开两倍大小的新表
// 2、遍历旧表,重新计算在新表中位置
// 3、释放旧表
vector newtables;
//size_t newsize = _tables.size() == 0 ? 10 : _tables.size() * 2;
// 开素数个空间提高效率
size_t newsize = GetNextPrime(_tables.size());
newtables.resize(newsize);
for (size_t i = 0; i < _tables.size(); i++)
{
// 将旧表的节点取下来重新计算在新表中的位置在插入
Node* cur = _tables[i];
while (cur)
{
Node* next = cur->_next;
size_t index = HashFunc(koft(cur->_data)) % newtables.size();
cur->_next = newtables[index];
newtables[index] = cur;
cur = next;
}
_tables[i] = nullptr; // 旧表置空
}
_tables.swap(newtables);
}
// 计算数据在表中的映射位置
size_t index = HashFunc(koft(data)) % _tables.size();
// 1、先查找这个值在不在表中
Node* cur = _tables[index];
while (cur)
{
if (koft(cur->_data) == koft(data))
{
return make_pair(iterator(cur,this),false);
}
else
{
cur = cur->_next;
}
}
// 2、头插到挂的链表中(尾插也可以)
Node* newnode = new Node(data);
newnode->_next = _tables[index];
_tables[index] = newnode;
++_num;
return make_pair(iterator(newnode, this), true);
}
// 获取素数
size_t GetNextPrime(size_t num) {
const int PRIMECOUNT = 28;
static const size_t primeList[PRIMECOUNT] =
{
// ul 无符号的长整型
// 素数
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
};
for (size_t i = 0; i < PRIMECOUNT; i++) {
if (primeList[i] > num) {
return primeList[i];
}
}
return primeList[PRIMECOUNT - 1];
}
Node* Find(const K& key)
{
KeyOfT koft;
size_t index = HashFunc(key) % _tables.szie();
Node* cur = _tables[index];
while (cur)
{
if (koft(cur->_data) == key)
{
return cur;
}
else
{
cur = cur->_next;
}
}
return nullptr;
}
bool Erase(const K& key)
{
KeyOfT koft;
size_t index = HashFunc(key) % _tables.size();
Node* prev = __nullptr;
Node* cur = _tables[index];
while (cur)
{
if (koft(cur->_data) == key)
{
if (prev == nullptr)
{
// 表示要删除的在第一个结点
_tables[index] = cur->_next;
}
else
{
prev->_next = cur->_next;
}
delete cur;
return true;
}
else
{
prev = cur;
cur = cur->_next;
}
}
return false;
}
private:
vector _tables; // 存的是节点的指针 指针数组
size_t _num = 0; // 记录表中储存的数据个数
};
}
#include"HashTable2.h"
using namespace OPEN_HASH2; // 展开这个命名空间 不然找不到HashTable
namespace hek {
template>
class unordered_set {
struct SetKOfT
{
const K& operator()(const K& k) {
return k;
}
};
public:
typedef typename HashTable::iterator iterator;
iterator begin() {
return _ht.begin();
}
iterator end() {
return _ht.end();
}
pair insert(const K& k) {
return _ht.Insert(k);
}
private:
HashTable _ht;
};
}
#include"HashTable2.h"
using namespace OPEN_HASH2;
namespace hek {
template>
class unordered_map {
struct MapKOfT
{
const K& operator()(const pair& kv) {
return kv.first;
}
};
public:
typedef typename HashTable, MapKOfT, Hash>::iterator iterator;
iterator begin() {
return _ht.begin();
}
iterator end() {
return _ht.end();
}
pair insert(const pair& kv) {
return _ht.Insert(kv);
}
V& operator[](const K& key) {
pair ret = _ht.Insert(make_pair(key, V()));
return ret.first->second;
}
private:
HashTable, MapKOfT, Hash> _ht;
};
}