首页 > 代码库 > 哈希桶的实现

哈希桶的实现

 

#pragma once
#include<vector>

template<class K>
struct __HashFunc
{
    size_t operator()(const K&key)
    {
        return key;
    }
};

template<>
struct __HashFunc<string>   //特化
{
    static size_t BKDRHash(const char*str)    //BKDRHash算法
    {

        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& str)
    {
        return BKDRHash(str.c_str());
    }
};

template<class K,class V>
struct KVNode
{
    K _key;
    V _value;
    KVNode<K, V>* _next;

    KVNode(const K& key, const V& value)
        :_key(key)
        , _value(value)
        , _next(NULL)
    {}
};
template<class K, class V, template<class> class HashFunc = __HashFunc>
class Hash
{
public:
      typedef KVNode<K, V> Node;
    Hash()     //构造函数
        :_size(0)
    {}

    ~Hash()     //析构函数
    {
        Clear();
    }

    Hash(const Hash& ht)    //拷贝构造函数
    {
        Copy(ht);
    }

    Hash& operator=(const Hash&ht)      //赋值运算符的重载
    {
        if (this != &ht)
        {
            Clear;
            Copy(ht);
        }
        return *this;
    }

    bool Insert(const K& key,const V& value)   //插入节点
    {
        _CheckSize();     //检查容量,看是否需要扩容
        size_t index = _HashFunc(key,_tables.size());
        if (Find(key))       //如果有这个值则说明不需要插入
            return false;
       
        //单链表的头插
        Node* head = _tables[index];
        Node* tmp = new Node(key, value);
        tmp->_next =head;
        _tables[index] = tmp;
        ++_size;
        return true;
    }

    //bool Insert(const K& key, const V&value)
    //{
    //    _CheckSize();
    //    size_t index = _HashFunc(key, _tables.size());
    //    Node*begin = _tables[index];
    //    while (begin)
    //    {
    //        if (begin->_key== key)
    //        {
    //            return false;
    //        }
    //        begin = begin->_next;
    //    }
    //    Node* head = _tables[index];
    //    Node* tmp = new Node(key, value);   //头插
    //    tmp->_next = head;
        /*_tables[index] = tmp;
        ++_size;
        return true;
    }*/

    /*bool Remove(const K& key)
    {
        size_t index = _HashFunc(key,_tables.size());
        Node* cur = _tables[index];
        Node* prev = NULL;
        while (cur)
        {
            if (cur->_key == key)
            {
                if (prev == NULL)
                    _tables[index] = cur->_next;
                else
                    prev->_next = cur->_next;
            
                delete cur;
                --_size;
                return true;
            }    
            prev = cur;
            cur = cur->_next;
        }
        return false;
    }*/

    bool Remove(const K& key)    //删除节点的函数
    {
        size_t index = _HashFunc(key, _tables.size());
        Node* cur = _tables[index];
        if (cur == NULL)
            return false;

        if (cur->_key == key)   //key为桶的头结点
        {
            _tables[index] = cur->_next;
            delete cur;
            --_size;
            return true;
        }

        Node* prev = cur;  //key为桶的中间节点
        cur = cur->_next;
        while (cur)
        {
            if (cur->_key == key)
            {
                prev->_next = cur->_next;
                delete cur;
                --_size;
                return true;
            }
            prev = prev;
            cur = cur->_next;
        }
        return false;
    }

    Node* Find(const K& key)    //查找节点
    {
        size_t index = _HashFunc(key,_tables.size());
        Node* cur = _tables[index];
        while (cur)
        {
            if (cur->_key == key)
                return cur;
            cur = cur->_next;
        }
        return NULL;
    }

    void Print()    //打印哈希桶
    {
        cout << "capacity" << "    " << "size" << ":" << _tables.size() << "   " << _size << endl;
        for (size_t i = 0; i < _tables.size(); ++i)
        {
            Node* cur = _tables[i];
            if (cur == NULL)
            {
                continue;
            }
            //cout << "[" << i << "]" << "    ";
            printf("【%d】", i);
            while (cur)
            {
                cout << "{" << cur->_key << "," << cur->_value << "}->";
                cur = cur->_next;
            }
            cout << "NULL" << endl;
        }
    }
//protected:
    void _CheckSize()     //检查容量,如果需要扩容就进行扩容
    {
        if (_size == 0 || _size == _tables.size())   
        {
            size_t capacity = _GetnextPrime(_size);
            vector<Node*> Hashtable;
            Hashtable.reserve(capacity);
            Hashtable.assign(capacity, 0);
            for (size_t i = 0; i < _tables.size(); ++i)
            {
                Node* begin = _tables[i];
                while (begin)
                {
                    Node* tmp = begin;
                    begin = begin->_next;

                    size_t index = _HashFunc(tmp->_key,capacity);

                    Node* head = Hashtable[index];
                    tmp->_next = head;
                    Hashtable[index] = tmp;
                }
            }
            _tables.swap(Hashtable);
        }
    }

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

    size_t _HashFunc(const K& key,size_t capacity)
    {
        return HashFunc<K>()(key) %capacity;
    }

    void Clear()   //素组中的元素是指针,因此要特别注意先释放每个节点下的单链表,否则造成内存泄漏
    {
        for (size_t i = 0; i < _tables.size(); ++i)
        {
            Node* cur = _tables[i];
            while (cur)
            {
                Node* del = cur;
                cur = cur->_next;
                delete del;
            }
            _tables[i] = NULL;
        }
    }

    void Copy(const Hash& ht)     //拷贝函数
    {
        _tables.resize(ht._tables.size());
        for (size_t i = 0; i < _tables.size(); ++i)
        {
            Node* cur = ht._tables[i];
            while (cur)
            {
                Node* newCur = new Node(cur->_key, cur->_value);
                newCur->_next = _tables[i];
                _tables[i] = newCur;
                cur = cur->_next;
            }
        }
    }
protected:
    vector<Node*> _tables;
    size_t _size;
};

哈希桶的实现