引子:我们在之前用红黑树来进行封装set与map二大容器,c++11引入了unordered_map,与unordered_set的新容器,这个底层就是哈希表!
告知:布隆过滤器,我只学了原理,下次,我再来代码呈现,我们也要进入c++的学习了,下次,更精彩(抱拳)
话不多说我们直接上代码,请君自行测试
Hash.h底层部分
#pragma once
#pragma once
#include<iostream>
#include<string>
#include<vector>
using namespace std;
//key要求有转整形的作用
template<class K>
class Hash_to_int
{
public:
size_t operator()(const K& key)
{
return (size_t)key;
}
};
//对于string类的转换--特化
template<>
class Hash_to_int<string>
{
public:
//仿函数
size_t operator()(const string& key)
{
size_t numi = 0;
for (auto e : key)
{
numi *= 131;
numi += e;
}
return numi;
}
};
namespace My_hash
{
//悬挂的节点
template<class T>
struct HashNode
{
T _data;
HashNode<T>* _next;
HashNode(const T& data)
:_data(data)
,_next(nullptr)
{}
};
//前置声明
template<class K, class T, class KeyofT,class hash= Hash_to_int<K>>
class HashTable;
//迭代器
template<class K, class T, class Ptr, class Ref,class KeyofT ,class hash = Hash_to_int<K>>
class Hash_iterator
{
public:
typedef HashNode<T> Node;
typedef Hash_iterator<K, T, Ptr, Ref,KeyofT,hash> Self;
Node* _node;
const HashTable<K, T,KeyofT,hash>* _table;
Hash_iterator(Node*node, const HashTable<K, T, KeyofT, hash>* table)
:_node(node)
,_table(table)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
Self& operator++()
{
if (_node->_next)
{
_node = _node->_next;
}
else
{
KeyofT kot;
hash to_int;
size_t numi = to_int(kot(_node->_data)) % _table->_tables.size();
++numi;
while (numi < _table->_tables.size())
{
if (_table->_tables[numi])
{
break;
}
++numi;
}
if (numi == _table->_tables.size())
_node = nullptr;
else
_node = _table->_tables[numi];
}
return *this;
}
};
template<class K, class T,class KeyofT,class hash>
class HashTable
{
public:
typedef HashNode<T> Node;
template<class K, class T, class Ptr, class Ref, class KeyofT,class hash >
friend class Hash_iterator;
//普通迭代器
typedef Hash_iterator<K, T, T*, T&,KeyofT,hash> Iterator;
//const迭代器
typedef Hash_iterator<K, T, const T*, const T&,KeyofT,hash> Const_Iterator;
public:
Iterator End()
{
return Iterator(nullptr, this);
}
Iterator Begin()
{
size_t numi = 0;
for (; numi < _tables.capacity(); ++numi)
{
if (_tables[numi])
break;
}
if (numi < _tables.capacity())
return Iterator(_tables[numi], this);
else
return Iterator(nullptr, this);
}
Const_Iterator End() const
{
return Const_Iterator(nullptr, this);
}
Const_Iterator Begin() const
{
if (_number == 0)
return End();
for (size_t i = 0; i < _tables.size(); i++)
{
Node* cur = _tables[i];
if (cur)
{
return Const_Iterator(cur, this);
}
}
return End();
}
HashTable()
:_number(0)
{
_tables.resize(10, nullptr);
}
~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;
}
}
//查找
Iterator Find(const K& key)
{
KeyofT kot;
hash to_int;
size_t hashi = to_int(key) % _tables.size();
Node* cur = _tables[hashi];
while (cur)
{
if (kot(cur->_data) == key)
{
return Iterator(cur, this);
}
cur = cur->_next;
}
return End();
}
//插入
pair<Iterator,bool> insert(const T&data)
{
KeyofT kot;
Iterator it = Find(kot(data));
if (it != End())
{
return make_pair(it,false);
}
hash to_int;
size_t numi = to_int(kot(data)) % _tables.size();
//负载因子为1时进行扩容
//即size与数据点相等
if (_number == _tables.size())
{
vector<Node*> newTable(_tables.size() * 2);
//挪动数据
for (size_t i = 0; i < _tables.size(); i++)
{
Node* current = _tables[i];
while (current)
{
Node* next = current->_next;
size_t numii = to_int(kot(current->_data)) % newTable.size();
// 头插到新表
current->_next = newTable[numii];
newTable[numii] = current;
current = next;
}
_tables[i] = nullptr;
}
_tables.swap(newTable);
}
//进行头插
Node* cmp = new Node(data);
cmp->_next = _tables[numi];
_tables[numi] = cmp;
_number++;
return make_pair(Iterator(cmp,this),true);
}
//删除
bool Erase(const K& key)
{
hash to_int;
//找出位置
size_t numi = to_int(key) % _tables.size();
Node* prev = nullptr;
Node* cur = _tables[numi];
while (cur)
{
if (cur->_data == key)
{
if (prev == nullptr)
{
_tables[numi] = cur->_next;
}
else
{
prev->_next = cur->_next;
}
delete cur;
_number--;
return true;
}
prev = cur;
cur = cur->_next;
}
return false;
}
// 新增遍历函数
void Traverse()
{
for (size_t i = 0; i < _tables.size(); i++)
{
KeyofT kot;
Node* current = _tables[i];
while (current)
{
cout << kot(current->_data)<< " "<< endl;
current = current->_next;
}
}
}
private:
vector<Node*> _tables;
size_t _number;
};
}
unordered_Map部分
#pragma once
#include"Hash.h"
//#include<unordered_map>
namespace My_Map
{
template<class K,class V,class hash=Hash_to_int<K>>
class unordered_Map
{
public:
class M_KeyofT
{
public:
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
typedef typename My_hash::HashTable<K, pair<const K, V>, M_KeyofT, hash>::Iterator iterator;
typedef typename My_hash::HashTable<K, pair<const K, V>, M_KeyofT, hash>::Const_Iterator const_iterator;
iterator begin()
{
return _cmp.Begin();
}
iterator end()
{
return _cmp.End();
}
const_iterator begin() const
{
return _cmp.Begin();
}
const_iterator end() const
{
return _cmp.End();
}
pair<iterator,bool> insert(const pair<K,V>& kv)
{
return _cmp.insert(kv);
}
//如果找到就是有重复值,find功能
//没有则为insert功能
V& operator[](const K& key)
{
pair<iterator, bool> ret = _cmp.insert(make_pair(key, V()));
return ret.first->second;
}
iterator Find(const K& key)
{
return _cmp.Find(key);
}
bool Erase(const K& key)
{
return _cmp.Erase(key);
}
private:
My_hash::HashTable<K, pair<const K,V>, M_KeyofT, hash>_cmp;
};
void test_map()
{
unordered_Map<string, string> dict;
dict.insert(make_pair("sort", "排序"));
dict.insert({ "left", "左边" });
dict.insert({ "right", "右边" });
dict["left"] = "左边,剩余";
dict["insert"] = "插入";
dict["string"];
for (auto e : dict)
{
cout << e.first << ":" << e.second << endl;
}
}
}
unordered_Set部分
#pragma once
#include"Hash.h"
namespace My_Set
{
template<class K, class hash = Hash_to_int<K>>
class unordered_Set
{
public:
class S_keyofT
{
public:
const K& operator()(const K& key)
{
return key;
}
};
typedef typename My_hash::HashTable<K, const K, S_keyofT, hash>::Iterator iterator;
typedef typename My_hash::HashTable<K, const K, S_keyofT, hash>::Const_Iterator const_iterator;
iterator begin()
{
return _cmp.Begin();
}
iterator end()
{
return _cmp.End();
}
const_iterator begin() const
{
return _cmp.Begin();
}
const_iterator end() const
{
return _cmp.End();
}
pair<iterator, bool> insert(const K& key)
{
return _cmp.insert(key);
}
iterator Find(const K& key)
{
return _cmp.Find(key);
}
bool Erase(const K& key)
{
return _cmp.Erase(key);
}
private:
My_hash::HashTable<K, const K, S_keyofT, hash>_cmp;
};
void Print(const unordered_Set<int>& s)
{
unordered_Set<int>::const_iterator it = s.begin();
while (it != s.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
struct Date
{
int _year;
int _month;
int _day;
bool operator==(const Date& d) const
{
return _year == d._year
&& _month == d._month
&& _day == d._day;
}
};
struct HashDate
{
size_t operator()(const Date& key)
{
// 112
// 121
return (key._year * 31 + key._month) * 31 + key._day;
}
};
void test_set()
{
unordered_Set<int> s;
int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14, 3,3,15 };
for (auto e : a)
{
s.insert(e);
}
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
unordered_Set<Date, HashDate> us;
us.insert({ 2024, 7, 25 });
us.insert({ 2024, 7, 26 });
for (auto e : us)
{
cout << e._year << " " << e._month << " " << e._day << endl;
}
}
}