HahTable——封装实现unordered_map和unordered _set

1 原理分析
容器unordered _ map和unordered _ set的底层是HashTable,本文简单实现容器unordered_map和unordered _set的功能,将前文中的HashTable进行封装,主要改插入和查找的返回类型,使之与库里的返回类型一致。
前文:https://blog.csdn.net/qq_15000103/article/details/80270980
STL中unordered _ map和unordered _ set成员函数如下:
1.1 unordered _ set
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
1.2 unordered _ map
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

2 代码模拟实现

//HashTable.h
#pragma once
#include<vector>
#include<utility>
#include<string>

template<class V>
struct HashNode
{
    V _v;//set->k;map->kv
    HashNode<V>* _next;
    HashNode(const V& v)
        :_v(v)
        , _next(NULL)
    {}
};

template<class K>
struct Hash
{
    size_t operator()(const K& key)
    {
        return key;
    }
};
template<>
struct Hash<string>//特化,使得缺省时,若调string,则调用此函数
{
    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);
    }

    size_t operator()(const string& key)
    {
        return BKDRHash(key.c_str());
    }
};

template<class K, class V, class KeyOfValue, class _HashFunc>//unordered_set<K,V>->HashTable<K,K>;unordered_map<K,V>->HashTable<K,pair<K,V>>
class HashTable;

template<class K, class V, class KeyOfValue, class _HashFunc>
struct _HashTableIterator//单向迭代器
{
    typedef HashNode<V> Node;
    typedef _HashTableIterator<K, V, KeyOfValue,_HashFunc> Self;
    typedef HashTable<K, V, KeyOfValue, _HashFunc> HT;

    Node* _node;
    HashTable<K, V, KeyOfValue, _HashFunc>* _ht;

    _HashTableIterator(Node* node, HT* ht)
        :_node(node)
        , _ht(ht)
    {}
    V& operator*()
    {
        return _node->_v;
    }
    V* operator->()
    {
        return &(operator*());
    }
    Self& operator++()
    {
        if (_node->_next)
        {
            _node = _node->_next;
        }
        else
        {
            KeyOfValue kov;
            size_t index = _ht->HashFunc(kov(_node->_v), _ht->_table.size());
            ++index;
            while (index < _ht->_table.size())
            {
                if (_ht->_table[index])
                {
                    _node = _ht->_table[index];
                    break;
                }
                else
                {
                    ++index;
                }
            }
            if (index == _ht->_table.size())
            {
                _node = NULL;
            }               
        }
        return *this;
    }
    Self operator++(int)
    {
        Self tmp(*this);
        ++*this;
        return tmp;
    }
    bool operator==(const Self& s )
    {
        return _node == s._node;
    }
    bool operator!=(const Self& s)
    {
        return _node != s._node;
    }
};

template<class K, class V,class KeyOfValue,class _HashFunc=Hash<K>>//unordered_set<K,V>->HashTable<K,K>;unordered_map<K,V>->HashTable<K,pair<K,V>>
class HashTable
{
    typedef HashNode<V> Node;
    friend struct _HashTableIterator<K, V, KeyOfValue,_HashFunc>;

public:
    typedef _HashTableIterator<K, V, KeyOfValue,_HashFunc> Iterator;
    Iterator Begin()
    {           
        for (size_t i = 0; i < _table.size(); i++)
        {
            if (_table[i])
            {
                return Iterator(_table[i], this);
            }
        }
        return End();
    }
    Iterator End()
    {
        return Iterator(NULL, this);
    }
    HashTable()
        : _size(0)
    {}
    std::pair<Iterator,bool> Insert(const V& v)
    {
        CheckCapacity();
        KeyOfValue kov;
        size_t index = HashFunc(kov(v), _table.size());

        Node* cur = _table[index];
        while (cur)
        {
            if (kov(cur->_v) == kov(v))
                return make_pair(Iterator(cur,this),false);
            cur = cur->_next;
        }
        Node* node = new Node(v);
        //头插
        node->_next = _table[index];
        _table[index] = node;
        ++_size;
        return make_pair(Iterator(node,this),true);
    }
    Iterator Find(const K& key)
    {
        size_t index = HashFunc(key);
        Node* cur = _table[index];
        KeyOfValue kov;
        while (cur)
        {
            if (kov(cur->_v) == key)
            {
                return Iterator(cur,this);
            }
            cur = cur->_next;
        }
        return Iterator(NULL,this);
    }
    bool Remove(const K& key)
    {
        KeyOfValue kov;
        size_t index = HashFunc(key);
        Node* cur = _table[index];
        if (cur == NULL)
        {
            return false;
        }
        if (kov(cur->_v) == key)//头删
        {
            _table[index] = cur->_next;
            delete cur;
            return true;
        }
        else//中间删
        {
            Node* prev = cur;
            cur = cur->_next;
            while (cur)
            {
                if (kov(cur->_v) == key)
                {
                    prev->_next = cur->_next;
                    delete cur;
                    return true;
                }
                prev = cur;
                cur = cur->_next;
            }
        }
        return true;
    }
    size_t HashFunc(const K& key, size_t size)
    {
        _HashFunc hf;
        return hf(key)%size;
    }

    size_t GetNextPrimeNum(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];
    }

    void CheckCapacity()
    {
        if (_table.size() == 0)
        {
            _table.resize(GetNextPrimeNum(0), NULL);
        }
        else if (_size == _table.size())//考虑负载因子
        {
            size_t newsize = GetNextPrimeNum(_table.size());
            if (newsize = _table.size())
            {
                return;
            }
            vector<Node*> newtable;
            newtable.resize(newsize, NULL);
            KeyOfValue kov;
            for (size_t i = 0; i < _table.size(); ++i)
            {
                Node* cur = _table[i];
                while (cur)
                {
                    size_t index = HashFunc(kov(cur->_v), newsize);
                    Node* next = cur->_next;
                    //头插到newtable;
                    cur->_next = newtable[index];//将cur指向新表的位置
                    newtable[index] = cur;

                    cur = next;
                }
                _table[i] = NULL;
            }
            _table.swap(newtable);
        }
    }
private:
    std::vector<Node*> _table;
    size_t _size;
};
//Myunorderedset.h
#pragma once
#include"HashTable.h"

template<class K,class HashFunc=Hash<K>>
class Myunorderedset
{
    struct SetKeyOfValue
    {
        const K&operator()(const K& key)
        {
            return key;
        }
    };
public: 
    typedef HASH_BUCKET::HashTable<K, K, SetKeyOfValue, HashFunc> HT;
    typedef typename HT::Iterator Iterator;
    std::pair<Iterator, bool> Insert(const K& key)
    {
        return _ht.Insert(key);
    }
    Iterator Find(const K& key)
    {
        return _ht.Find(key);
    }
    Iterator Begin()
    {
        return _ht.Begin();
    }
    Iterator End()
    {
        return _ht.End();
    }
private:
    HT _ht;
};
//Myunorderedmap.h
#pragma once

template<class K, class V, class HashFunc = Hash<K>>
class Myunorderedmap
{
    struct MapKeyOfValue
    {
        const K&operator()(const std::pair<K, V>& kv)
        {
            return kv.first;
        }
    };
public:
    typedef HASH_BUCKET::HashTable<K, std::pair<K, V>, MapKeyOfValue, HashFunc> HT;
    typedef typename HT::Iterator Iterator;
    std::pair<Iterator, bool> Insert(const std::pair<K,V>& kv)
    {
        return _ht.Insert(kv);
    }
    Iterator Find(const K& key)
    {
        return _ht.Find(key);
    }
    V& operator [](const K& key)
    {
        std::pair<Iterator, bool> ret = _ht.Insert(make_pair(key,V()));
        return ret.first->second;

    }
    Iterator Begin()
    {
        return _ht.Begin();
    }
    Iterator End()
    {
        return _ht.End();
    }
private:
    HT _ht;
};
//TestMyunorderedset.cpp
void TestMyunorderedset()
{
    Myunorderedset<string> s;
    s.Insert("sort");
    s.Insert("left");
    s.Insert("string");
    s.Insert("char");
    s.Insert("char");
    Myunorderedset<string>::Iterator it = s.Begin();
    while (it != s.End())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;
}
//TestMyunorderedmap.cpp
void TestMyunorderedmap()
{
    Myunorderedmap<string, string> dict;
    dict.Insert(make_pair("string", "字符串"));
    dict.Insert(make_pair("left", "左边"));
    dict.Insert(make_pair("left", "剩下"));
    dict["left"] = "剩余";
    dict["map"] = "映射";

    Myunorderedmap<string, string>::Iterator it = dict.Begin();
    while (it != dict.End())
    {
        cout << it->first << ":" << it->second << endl;
        ++it;
    }
}

测试结果:
这里写图片描述
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值