hashtables之哈希桶法

来源:互联网 发布:怎么查看服务器端口 编辑:程序博客网 时间:2024/05/19 15:43
#pragma once#include<iostream>#include<vector>#include<string>using namespace std;template<class K,class V>struct HashTablesNode{    K _key;    V _value;    struct HashTablesNode* next;    HashTablesNode(const K& key, const V& value)        : _key(key)        , _value(value)        , next(NULL)    {}};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);}//为string定制的仿函数struct __HashFuncS{    size_t operator()(const string& str)    {        return BKDRHash(str.c_str());    }};//对 int型struct __HashFuncInt{    size_t operator()(const int& key)    {        return key;    }};template<class K, class V, class H = __HashFuncInt >class HashTables{    typedef HashTablesNode<K,V> Node;public:    HashTables()    {}    HashTables(size_t _size)     {        _table.resize(GetNextCapacity(size));    }    void print()    {        for (size_t i = 0; i < _table.size();++i)        {            printf("_hashtable[%d]->", i);            Node* pcur = _table[i];            while (pcur)            {                cout << pcur->_key << " :"<<pcur->_value<<"  ";                pcur = pcur->next;            }            cout << endl;        }    }    bool Find(const K& key)    {        int index = _HashFunc(key,_table.size());        Node* pcur = _table[index];        while (pcur)        {            if (pcur->_key == key)                return true;            pcur = pcur->next;        }        return false;    }    bool Insert(const K& key, const V& value)    {        CheckCapacity();        if (Find(key))            return false;        int index = _HashFunc(key,_table.size());        Node* tmp = new Node(key, value);        tmp->next = _table[index];        _table[index] = tmp;        size++;        return true;    }    bool Remove(const K& key)    {        size_t index = _HashFunc(key, _table.size());        Node* pcur = _table[index];        if (pcur->_key == key)            _table[index] = pcur->next;        else        {            while (pcur)            {                Node* prev = pcur;                pcur = pcur->next;                if (pcur->_key == key)                {                    prev->next = pcur->next;                }            }            if (pcur == NULL)                return false;        }        delete pcur;        size--;        return true;    }private:    size_t GetNextCapacity(size_t size)    {        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 (size < _PrimeList[i])                return _PrimeList[i];        }        return _PrimeList[_PrimeSize];    }    size_t _HashFunc(const K& key, size_t size)//除留余数法    {        return H()(key) % size;    }    void CheckCapacity()    {        if (size == _table.size())//负载因子达到1.0        {            //_table.resize(size * 2 + 3);            vector<Node*> newtable;            newtable.resize(GetNextCapacity(size));            for (size_t i = 0; i < _table.size(); ++i)            {                Node* pcur = _table[i];                while (pcur)                {                    Node* pnext = pcur->next;                    //                    int index = _HashFunc(pcur->_key, newtable.size());                    pcur->next = newtable[index];                    newtable[index] = pcur;                    _table[i] = pnext;                    pcur = _table[i];                }            }            swap(newtable, _table);        }    }private:    vector<Node*> _table;    size_t size;};

用了素数表来配合除留余数法来减少冲突,用了哈希桶来处理哈希碰撞;
哈希表每个元素都是一个指针,指向一个单链表的第一个节点。插入数据就是往对应的key下面挂节点,查找的时候直接定位到对应的哈希表的位置,然后遍历单链表查找。对于这个单链表也可以其他方式来组织,如红黑树,让哈希表里面保存红黑树的根节点指针即可;
哈希桶的做法,相对于二次探测和线性探测,减少了前面数据对本次插入数据的影响。时间复杂度实际上通过优化可以达到0(1);缺点是比较浪费空间;

0 0
原创粉丝点击