hashtables之哈希桶法

#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);缺点是比较浪费空间;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值