在代码中实现了哈希表中任意类型都可以存放,即哈希函数要可扩展以及哈希表动态增容的功能。
贴上代码:
#include<iostream>
#include<vector>
using namespace std;
template<class K>//特化
class _HashFun
{
public:
size_t operator()(K key)
{
return key;
}
};
template<>
class _HashFun<string>
{
public:
size_t operator()(const char* str)
{
return BKDRHash(str);
}
private:
static size_t BKDRHash(const char * str)
{
unsigned int seed = 131; // 31 131 1313 13131 131313
unsigned int hash = 0;
while (*str )
{
hash = hash * seed + (*str++);
}
return (hash & 0x7FFFFFFF);
}
};
enum State //状态标志
{
EXIST,
EMPTY,
DELETE,
};
template<class K, class V>
struct HashElem //哈希元素
{
HashElem()
:_s(EMPTY)
{}
pair<K, V> _kv;
State _s;
};
template<class K, class V, class HashFunc = _HashFun<K>, bool Isline = true>
class HashTable //哈希表
{
public:
HashTable(size_t size = 12)
:_size(0)
{
_table.resize(size);
}
bool Insert(const K& key, const V& value)
{
_CheckTable();
//如果表满
if(_size == _table.size())
return false;
size_t hashAddr = _HashFunc(key);//找哈希地址
size_t H0 = hashAddr;
size_t i = 1;
while(EXIST == _table[hashAddr]._s)//冲突
{
if(key == _table[hashAddr]._kv.first)//只插入唯一值
return false;
if(Isline)
{
hashAddr = HashFunc1(H0);
}
else
{
hashAddr = HashFunc2(H0, i);
}
i++;
//hashAddr++;//线性探测
//if(hashAddr == _table.size())//找到最后一个再从头开始
// hashAddr = 0;
}
//插入
_table[hashAddr]._kv.first = key;
_table[hashAddr]._kv.second = value;
_table[hashAddr]._s = EXIST;
_size++;
return true;
}
pair<HashElem<K,V>*, bool> Find(const K& key)//查找值为key的元素
{
size_t hashAddr = _HashFunc(key);
size_t H0 = hashAddr;
size_t i = 1;
while(EMPTY != _table[hashAddr]._s)
{
if(_table[hashAddr]._kv.first == key)
{
if(_table[hashAddr]._s == EXIST)
return make_pair(&_table[hashAddr], true);
else//DELETE
return make_pair((HashElem<K, V>*)NULL, false);//这里需要强转,否则编译器可能将NULL当成0
}
if(Isline)
{
hashAddr = HashFunc1(H0);
}
else
{
hashAddr = HashFunc2(H0, i);
}
i++;
//hashAddr++;//线性探测
//if(hashAddr == _table.size())
// hashAddr = 0;
}
return make_pair((HashElem<K,V>*)NULL,false);
}
bool Remove(const K& key)//删除
{
pair<HashElem<K, V>*, bool> pos = Find(key);
if(pos.second)
{
pos.first->_s = DELETE;
_size--;
return true;
}
return false;
}
private:
size_t _HashFunc(const K& key)
{
return HashFunc()(key) % 10/*_table.size()-1*/;
}
// 线性探测处理函数
size_t HashFunc1(size_t hashAddr)
{
hashAddr++;
if(hashAddr == _table.size())
hashAddr = 0;
return hashAddr;
}
// 二次探测处理函数
size_t HashFunc2(size_t hashAddr, size_t i)
{
if(hashAddr >= _table.size())
hashAddr = 0;
return hashAddr+2*i+1;
}
void Swap(HashTable<K,V>& ht)
{
_table.swap(ht._table);//两个容器交换不创建临时对象
swap(_size, ht._size);
}
void _CheckTable()
{
if(_size*10 / _table.size() >= 7)
{
size_t newsize = _table.size()*2;//乘2可能会越界
//newsize = GetNextPrime(newsize);
//交换法 销毁原来的空间
HashTable<K, V> ht(newsize);
for(int idx = 0;idx <= _table.size();idx++)
{
if(_table[idx]._s == EXIST)
ht.Insert(_table[idx]._kv.first, _table[idx]._kv.second);
}
Swap(ht);
}
}
vector<HashElem<K, V>> _table;
size_t _size;//有效元素的个数
};
void FunTest()
{
int a[] = {11,25,37,14,36,49,57};
HashTable<int, int> ht;
for(int idx = 0; idx <sizeof(a)/sizeof(a[0]); idx++)
ht.Insert(a[idx], idx);
pair<HashElem<int, int>*, bool> pos = ht.Find(25);
if(pos.second)
{
cout<<pos.first->_kv.first<<endl;
}
else
{
cout<<"没有找到该元素"<<endl;
}
ht.Remove(25);
pair<HashElem<int, int>*, bool> pos1 = ht.Find(25);
if(pos1.second)
{
cout<<pos1.first->_kv.first<<endl;
}
else
{
cout<<"没有找到该元素"<<endl;
}
}