基于模拟实现的哈希桶,我们来模拟实现STL中的unordered_set和unordered_map
哈希表的模拟实现请参照:【数据结构】哈希Hash-CSDN博客
总的来说,他们实现的大体思路是一样的,都是对哈希表进行封装。
一、unordered_set
//仿函数class Hash:传给unordered_set,再传给哈希表
//默认的仿函数直接返回key:因为有些类型的key直接就可以取模
template<class K>
struct _Hash
{
const K& operator()(const K& key)
{
return key;
}
};
//模版特化:针对某些特殊类型 给出特殊的处理
template<>
struct _Hash<string>
{
size_t operator()(const string& key)
{
//BKDR算法
size_t hash = 0;
for(size_t i=0; i<key.size(); i++)
{
hash *= 131;//乘上131后效果最好
hash += key[i];
}
return hash;
}
};
//模拟实现的unordered_set
template<class K, class Hash = _Hash<K>>
class unordered_set
{
//仿函数:传给哈希表的,作用是取出key
struct SetKeyOfV
{
const K& operator()(const K& key){return key;}
};
public:
typedef typename HashTable<K, K, SetKeyOfV, Hash>::iterator iterator;
//复用哈希表里对应的接口
iterator begin(){return _ht.begin();}
iterator end(){return _ht.end();}
pair<iterator, bool> Insert(const K& k){return _ht.Insert(k);}
private:
HashTable<K, K, SetKeyOfV, Hash> _ht;
};
复用哈希表的接口很好理解,重点要看的是仿函数的实现(_Hash 和 SetKeyOfV)。
其中仿函数_Hash的实现还运用了模板特化,因为想给模板里的仿函数一个缺省值
template<class K, class Hash = _Hash<K>>
但是常用类型和字符串处理方法不一样,所以需要对字符串的进行单独处理,所以需要模板特化
二、unordered_map
//仿函数class Hash:传给unordered_set,再传给哈希表
//默认的仿函数直接返回key:因为有些类型的key直接就可以取模
template<class K>
struct _Hash
{
const K& operator()(const K& key)
{
return key;
}
};
//模版特化:针对某些特殊类型 给出特殊的处理
template<>
struct _Hash<string>
{
size_t operator()(const string& key)
{
//BKDR算法
size_t hash = 0;
for(size_t i=0; i<key.size(); i++)
{
hash *= 131;//乘上131后效果最好
hash += key[i];
}
return hash;
}
};
//模拟实现的unordered_map
template<class K, class V, class Hash = _Hash<K>>
class unordered_map
{
//仿函数:传给哈希表的,作用是取出key
struct MapKeyOfV
{
const K& operator()(const pair<K, V>& kv){return kv.first;}
};
public:
typedef typename HashTable<K, pair<K, V>, MapKeyOfV, Hash>::iterator iterator;
//复用哈希表里对应的接口
iterator begin(){return _ht.begin();}
iterator end(){return _ht.end();}
pair<iterator, bool> Insert(const pair<K, V>& kv){return _ht.Insert(kv);}
//实现的operator[]
V& operator[](const K& key)
{
pair<iterator, bool> ret = _ht.Insert(make_pair(key, V()));
return (ret.first)->second;
}
private:
HashTable<K, pair<K, V>, MapKeyOfV, Hash> _ht;
};
实现的方法和需要注意的点和unordered_set一样,所以这里不在重复。