哈希表的模拟实现
#pragma once
#include<iostream>
#include<vector>
using namespace std;
namespace Closed
{
enum STATE{EMPTY,DELETE,EXIST};
template <class K,class V>
class HashNode{
public:
pair<K,V> _kv;
STATE _state=EMPTY;
};
template<class K,class V>
class HashTable{
public:
typedef HashNode<K,V> Node;
typedef Node* pNode;
public:
HashTable(size_t N=5){
_table.resize(N);
_size=0;
}
bool Insert(const pair<K,V>& kv){
CheckCapacity();
size_t index=kv.first%_table.size();
while(_table[index]._state==EXIST){
if(_table[index]._kv.first==kv.first){
return false;
}
++index;
if(index==_table.size()){
index=0;
}
}
_table[index]._kv=kv;
_table[index]._state=EXIST;
++_size;
return true;
}
pNode Find(const K& key){
size_t index=key%_table.size();
while(_table[index]._state!=EMPTY){
if(_table[index]._state==EXIST && _table[index]._kv.first==key){
return &_table[index];
}
++index;
if(index==_table.size()){
index=0;
}
}
return nullptr;
}
bool Erase(const K& key){
pNode ret=Find(key);
if(ret){
ret->_state=DELETE;
--_size;
return true;
}
return false;
}
void CheckCapacity(){
if(_table.size()==0 || _size*10 / _table.size()>=7){
size_t newC=( _table.size()==0?10:2*_table.size() );
HashTable<K,V> newHt(newC);
for(size_t i=0;i<_table.size();i++){
if(_table[i]._state==EXIST){
newHt.Insert(_table[i]._kv);
}
}
_table.swap(newHt._table);
}
}
private:
vector<Node> _table;
size_t _size;
};
}
template <class V>
struct HashNode{
HashNode<V>* _next;
V _data;
HashNode(const V& data)
:_next(nullptr)
,_data(data)
{
}
};
template<class K,class V,class KeyOfValue,class HashFun>
class HashTable;
template<class K,class V,class KeyOfValue,class HashFun>
struct Hash_Iterator{
typedef HashNode<V> Node;
typedef Node* pNode;
typedef Hash_Iterator<K,V,KeyOfValue,HashFun> Self;
typedef HashTable<K,V,KeyOfValue,HashFun> HashT;
pNode _node;
HashT* _ht;
Hash_Iterator(pNode node,HashT* ht)
:_node(node)
,_ht(ht)
{
}
V& operator*(){
return _node->_data;
}
V* operator->(){
return &(operator*());
}
bool operator!=(const Self& it){
return _node != it._node;
}
Self& operator++(){
if(_node->_next){
_node=_node->_next;
}else{
KeyOfValue Kov;
size_t index=_ht->HashIndex( Kov(_node->_data),_ht->_table.size() );
++index;
for(;index<_ht->_table.size();++index){
if(_ht->_table[index]){
_node= _ht->_table[index];
break;
}
}
if(index==_ht->_table.size()){
_node=nullptr;
}
}
return *this;
}
};
template <class K,class V,class KeyOfValue,class HashFun>
class HashTable{
public:
typedef HashNode<V> Node;
typedef Node* pNode;
template<class Key,class Val,class SKeyOfValue,class SHashFun>
friend struct Hash_Iterator;
typedef Hash_Iterator<K,V,KeyOfValue, HashFun> Iterator;
public:
Iterator begin(){
for(size_t i=0;i<_table.size();++i){
if(_table[i]){
return Iterator(_table[i],this);
}
}
return Iterator(nullptr,this);
}
Iterator end(){
return Iterator(nullptr,this);
}
public:
pair<Iterator,bool> Insert(const V& data){
CheckCapacity();
KeyOfValue Kov;
size_t index=HashIndex(Kov(data),_table.size());
pNode cur=_table[index];
while(cur){
if(Kov(cur->_data)== Kov(data)){
return make_pair(Iterator(cur,this),false);
}
cur=cur->_next;
}
cur=new Node(data);
cur->_next=_table[index];
_table[index]=cur;
++_size;
return make_pair(Iterator(cur,this),true);
}
size_t getNextPrime(const size_t prime)
{
static 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
};
for (size_t i = 0; i < PRIMECOUNT; ++i)
{
if (primeList[i] > prime)
return primeList[i];
}
return primeList[PRIMECOUNT - 1];
}
void CheckCapacity(){
if(_size==_table.size()){
size_t newC=getNextPrime(_table.size());
KeyOfValue Kov;
vector<pNode> newHt;
newHt.resize(newC);
for(size_t i=0;i<_table.size();i++){
pNode cur=_table[i];
while(cur){
pNode next=cur->_next;
size_t index=HashIndex(Kov(cur->_data),newHt.size());
cur->_next=newHt[index];
newHt[index]=cur;
cur=next;
}
_table[i]=nullptr;
}
_table.swap(newHt);
}
}
Iterator Find(const K& key){
size_t index=HashIndex(key,_table.size());
pNode cur=_table[index];
KeyOfValue kov;
while(cur){
if(kov(cur->data)==key)
return Iterator(cur,this);
}
return end();
}
bool Erase(const K& key){
size_t index=HashIndex(key,_table.size());
pNode cur=_table[index];
pNode prev=nullptr;
KeyOfValue kov;
while(cur){
if(kov(cur->_data)==key){
if(prev){
prev->_next=cur->_next;
}
else
_table[index]=cur->_next;
delete cur;
--_size;
return true;
}
prev =cur;
cur=cur->_next;
}
return false;
}
size_t HashIndex(const K& key,size_t sz){
HashFun hfun;
return hfun(key)%sz;
}
private:
vector<pNode> _table;
size_t _size=0;
};
unoredred_map/unordered_set封装
#pragma once
#include"hash.hpp"
#include<string>
template <class K>
struct HFun{
const K&operator()(const K&a){
return a;
}
};
template<>
struct HFun<string>{
size_t operator()(const string& str){
size_t hash=0;
for(const auto& e:str){
hash=hash*131 +e;
}
return hash;
}
};
template <class K,class V,class HashFun=HFun<K>>
class UnorderedMap{
public:
typedef pair<K,V> ValueType;
struct MapKeyOfValue{
const K& operator()(const pair<K,V>& data){
return data.first;
}
};
public:
typedef typename HashTable<K,ValueType,MapKeyOfValue,HashFun>::Iterator Iterator;
V& operator[](const K& key){
pair<Iterator,bool> ret=_ht.Insert(key);
return ret.first->second;
}
Iterator Begin(){
return _ht.begin();
}
Iterator End(){
return _ht.end();
}
public:
pair<Iterator,bool> Insert(const pair<K,V>& data){
return _ht.Insert(data);
}
private:
HashTable<K,ValueType,MapKeyOfValue,HashFun> _ht;
};
template <class K,class HashFun=HFun<K>>
class UnorderedSet{
public:
struct SetKeyOfValue{
const K& operator()(const K& data){
return data;
}
};
typedef typename HashTable<K,K,SetKeyOfValue,HashFun>::Iterator Iterator;
Iterator Begin(){
return _ht.begin();
}
Iterator End(){
return _ht.end();
}
public:
pair<Iterator,bool> Insert(const K& data){
return _ht.Insert(data);
}
private:
HashTable<K,K,SetKeyOfValue,HashFun> _ht;
};
测试
#include"hash.hpp"
#include"Unordered_map_set.hpp"
#include"bitSet.hpp"
void TestUnordered(){
UnorderedMap<int,int> map;
map.Insert(make_pair(1,1));
map.Insert(make_pair(2,2));
map.Insert(make_pair(3,3));
map.Insert(make_pair(4,4));
map.Insert(make_pair(5,5));
UnorderedMap<int,int>::Iterator mit=map.Begin();
while(mit!=map.End()){
cout<<mit->first<<"-->"<<mit->second<<endl;
++mit;
}
UnorderedSet<int> set;
set.Insert(1);
set.Insert(2);
set.Insert(3);
set.Insert(4);
set.Insert(5);
UnorderedSet<int>::Iterator sit=set.Begin();
while(sit!=set.End()){
cout<<*sit<<endl;
++sit;
}
UnorderedMap<string,string> m;
m.Insert(make_pair("my","name"));
m.Insert(make_pair("you","name"));
auto it1=m.Begin();
while(it1!=m.End()){
cout<<it1->first<<"-->"<<it1->second<<endl;
++it1;
}
}
int main(){
TestUnordered();
return 0;
}
测试结果展示