哈希桶的实现
#pragma once
#include<vector>
template<class K>
struct __HashFunc
{
size_t operator()(const K&key)
{
return key;
}
};
template<>
struct __HashFunc<string> //特化
{
static size_t BKDRHash(const char*str) //BKDRHash算法
{
unsigned int seed = 131;// 31 131 1313 13131 131313
unsigned int hash= 0;
while (*str)
{
hash = hash*seed + (*str++);
}
return(hash & 0x7FFFFFFF);
}
size_t operator()(const string& str)
{
return BKDRHash(str.c_str());
}
};
template<class K,class V>
struct KVNode
{
K _key;
V _value;
KVNode<K, V>* _next;
KVNode(const K& key, const V& value)
:_key(key)
, _value(value)
, _next(NULL)
{}
};
template<class K, class V, template<class> class HashFunc = __HashFunc>
class Hash
{
public:
typedef KVNode<K, V> Node;
Hash() //构造函数
:_size(0)
{}
~Hash() //析构函数
{
Clear();
}
Hash(const Hash& ht) //拷贝构造函数
{
Copy(ht);
}
Hash& operator=(const Hash&ht) //赋值运算符的重载
{
if (this != &ht)
{
Clear;
Copy(ht);
}
return *this;
}
bool Insert(const K& key,const V& value) //插入节点
{
_CheckSize(); //检查容量,看是否需要扩容
size_t index = _HashFunc(key,_tables.size());
if (Find(key)) //如果有这个值则说明不需要插入
return false;
//单链表的头插
Node* head = _tables[index];
Node* tmp = new Node(key, value);
tmp->_next =head;
_tables[index] = tmp;
++_size;
return true;
}
//bool Insert(const K& key, const V&value)
//{
// _CheckSize();
// size_t index = _HashFunc(key, _tables.size());
// Node*begin = _tables[index];
// while (begin)
// {
// if (begin->_key== key)
// {
// return false;
// }
// begin = begin->_next;
// }
// Node* head = _tables[index];
// Node* tmp = new Node(key, value); //头插
// tmp->_next = head;
/*_tables[index] = tmp;
++_size;
return true;
}*/
/*bool Remove(const K& key)
{
size_t index = _HashFunc(key,_tables.size());
Node* cur = _tables[index];
Node* prev = NULL;
while (cur)
{
if (cur->_key == key)
{
if (prev == NULL)
_tables[index] = cur->_next;
else
prev->_next = cur->_next;
delete cur;
--_size;
return true;
}
prev = cur;
cur = cur->_next;
}
return false;
}*/
bool Remove(const K& key) //删除节点的函数
{
size_t index = _HashFunc(key, _tables.size());
Node* cur = _tables[index];
if (cur == NULL)
return false;
if (cur->_key == key) //key为桶的头结点
{
_tables[index] = cur->_next;
delete cur;
--_size;
return true;
}
Node* prev = cur; //key为桶的中间节点
cur = cur->_next;
while (cur)
{
if (cur->_key == key)
{
prev->_next = cur->_next;
delete cur;
--_size;
return true;
}
prev = prev;
cur = cur->_next;
}
return false;
}
Node* Find(const K& key) //查找节点
{
size_t index = _HashFunc(key,_tables.size());
Node* cur = _tables[index];
while (cur)
{
if (cur->_key == key)
return cur;
cur = cur->_next;
}
return NULL;
}
void Print() //打印哈希桶
{
cout << "capacity" << " " << "size" << ":" << _tables.size() << " " << _size << endl;
for (size_t i = 0; i < _tables.size(); ++i)
{
Node* cur = _tables[i];
if (cur == NULL)
{
continue;
}
//cout << "[" << i << "]" << " ";
printf("【%d】", i);
while (cur)
{
cout << "{" << cur->_key << "," << cur->_value << "}->";
cur = cur->_next;
}
cout << "NULL" << endl;
}
}
//protected:
void _CheckSize() //检查容量,如果需要扩容就进行扩容
{
if (_size == 0 || _size == _tables.size())
{
size_t capacity = _GetnextPrime(_size);
vector<Node*> Hashtable;
Hashtable.reserve(capacity);
Hashtable.assign(capacity, 0);
for (size_t i = 0; i < _tables.size(); ++i)
{
Node* begin = _tables[i];
while (begin)
{
Node* tmp = begin;
begin = begin->_next;
size_t index = _HashFunc(tmp->_key,capacity);
Node* head = Hashtable[index];
tmp->_next = head;
Hashtable[index] = tmp;
}
}
_tables.swap(Hashtable);
}
}
size_t _GetnextPrime(size_t num)
{
const int _Primesize = 28;
static const unsigned long _PrimeList[_Primesize] =
{
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 < _Primesize; ++i)
{
if (_PrimeList[i]>num)
{
return _PrimeList[i];
}
return _PrimeList[_Primesize - 1];
}
}
size_t _HashFunc(const K& key,size_t capacity)
{
return HashFunc<K>()(key) %capacity;
}
void Clear() //素组中的元素是指针,因此要特别注意先释放每个节点下的单链表,否则造成内存泄漏
{
for (size_t i = 0; i < _tables.size(); ++i)
{
Node* cur = _tables[i];
while (cur)
{
Node* del = cur;
cur = cur->_next;
delete del;
}
_tables[i] = NULL;
}
}
void Copy(const Hash& ht) //拷贝函数
{
_tables.resize(ht._tables.size());
for (size_t i = 0; i < _tables.size(); ++i)
{
Node* cur = ht._tables[i];
while (cur)
{
Node* newCur = new Node(cur->_key, cur->_value);
newCur->_next = _tables[i];
_tables[i] = newCur;
cur = cur->_next;
}
}
}
protected:
vector<Node*> _tables;
size_t _size;
};