【C++】unordered_set和unordered_map的模拟实现

本文详细介绍了如何在C++中模拟实现STL中的unordered_set和unordered_map,重点讲解了仿函数的实现,包括默认仿函数和针对字符串的模板特化。
摘要由CSDN通过智能技术生成

基于模拟实现的哈希桶,我们来模拟实现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;
};

复用哈希表的接口很好理解,重点要看的是仿函数的实现(_HashSetKeyOfV)。

其中仿函数_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一样,所以这里不在重复。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值