哈希算法可以说是效率比较高的一种算法了,基本上时间复杂度为 O(1)。但哈希有个坑爹的地方就是碰撞问题。当发生冲突时,有两种解决办法:
具体算法不再解释,以下代码使用 STL 中 vector 和 list 实现了一个基于哈希桶的哈希表。
代码如下:
#pragma once
#include<iostream>
#include<vector>
#include<list>
using namespace std;
//template<typename key_type,typename value_type>
//struct Pair<key_type,value_type>
//{
// key_type _first;
// value_type _second;
//};
template<typename key_type,typename value_type>
bool operator==(const pair<key_type,value_type>& p1,const pair<key_type,value_type>& p2)
{
if(p1.first==p2.first)
return true;
return false;
}
template<typename key_type>
struct HashFunc{
size_t operator()(const key_type* key)
{
return BKDRHash(key);
}
size_t BKDRHash(const key_type* str)
{
register size_t hash=0;
while(size_t ch=(size_t)*str++)
{
hash=hash*131+ch;
}
return hash;
}
};
template<typename key_type,typename value_type,typename Hash=HashFunc<key_type>>
class HashTable{
public:
HashTable()
:_size(0)
{
HashBase.resize(_GetNextSize());
}
bool Insert(const key_type& key,const value_type& value)
{
if(Find(key))
return false;
size_t index=_Hash(key);
HashBase[index].insert(pair<key_type,value_type>(key,value));
return true;
}
bool Find(const key_type& key)
{
size_t index=_Hash(key);
if(find(HashBase[index].begin(),HashBase[index].end(),key)!=HashBase[index].end())
return false;//the key has existed!
return true;
}
protected:
size_t _Hash(const key_type& key)
{
Hash hs;
return hs(key)%_size;
}
size_t _GetNextSize()
{
enum {__stl_num_primes=28};
static const size_t __stl_prime_list[__stl_num_primes] =
{
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
};
size_t size=HashBase.size();
int i;
for(i=0;i<__stl_num_primes;++i)
{
if(__stl_prime_list[i]>size)
return __stl_prime_list[i];
}
return __stl_prime_list[__stl_num_primes-1];
}
private:
vector<list<pair<key_type,value_type> > > HashBase;
size_t _size;
};
如果你有任何想法或是可以改进的地方,欢迎和我交流!
完整代码及测试用例在 github 上:点我前往