数据结构—Hashtable(闭散列)

哈希表是常见数据结构中一种拥有高效插入,高效查找的结构,时间复杂度为O(1)。

闭散列哈希的不足之处就是随着冲突的数据增多,插入的效率也会随之变慢,为了优化闭散列哈希的效率,我们可以采取以下的方式:

>1.当插入的数据占总大小的一定比率的时候,也称负载因子,我们可以对哈希表进行扩容,重新通过哈希函数求得位置插入。
>2.我们可以采用素数表的形式,来减少哈希冲突的可能。
>3.通过更好优化的哈希函数,来减少冲突的可能。

这里写图片描述
每次扩容,带来的也是巨大的开销,首先要开辟新的空间,其次,重新插入需要通过哈希函数重新求得新插入的位置。
1。我们通过对每个哈希节点进行标记,三种标记分别为EMPTY空白,DELETE删除,EXIST存在。分别表示此处没有插入过数据,插入过数据但当前位置数据已经删除,此处存在数据。
2。当我们进行查找的时候,如果前k值通过哈希函数求得位置向后查找,如果为EMPTY则停下,当找到表的尾部,然后从0开始继续查找。
3。当我们插入的时候,同理求得插入位置,如果该位置已经有值,我们向后查找,当遇到EMPTY或者DELETE时,该位置没有数据,在该位置插入。

我们在插入时,通过函数CheckLoadFactor()来检测当前负载因子,当负载因子当到我们设定的比率时,我们采用对哈希表进行扩,扩容的大小为每次素数表中的下一个素数大小。
本次哈希表中的哈希函数,使用的是直接定值法。

#include<iostream>
#include<vector>
using namespace std;

enum condition
{
    EMPTY,
    DELETE,
    EXIST,
};

template<class K, class V>
struct Hashnode
{
    K key;
    V value;
    condition con;

    Hashnode(const K k = K(), const V v = V())
        :key(k)
        , value(v)
        , con(EMPTY)
    {}
};

template<class K>
struct HashFun
{
    size_t operator()(K k)
    {
        return k;
    }
};

template<class K, class V, class __HashFun = HashFun<K> >
class Hashtable
{
public:
    typedef Hashnode<K, V> node;

    Hashtable()
        :size(0)
    {}

    Hashtable(const Hashtable& h)
        :size(0)
    {
        for (size_t index = 0; index<h.table.size(); index++)
        {
            Insert(h.table[index].key, h.table[index].value);
        }
    }

    Hashtable& operator=(Hashtable h)
    {
        table.swap(h.table);
        swap(size, h.size);
        return *this;
    }

    bool Insert(K k, V v)
    {
        CheckLoadFactor();
        size_t index = Hashfun(k);
        while (table[index].key = k || (table[index].key = k&&table[index].con != EXIST))
        {
            if (table[index].con != EXIST)
            {
                table[index].key = k;
                table[index].value = v;
                table[index].con = EXIST;
                size++;
                return true;
            }
            index++;
            if (index>table.size())
            {
                index = 0;
            }
        }
        return false;
    }

    size_t Hashfun(const K& k)
    {
        __HashFun hashfun;
        return hashfun(k) % table.size();
    }

    node* Find(const K& k)
    {
        size_t index = Hashfun(k);
        while (table[index].con != EMPTY)
        {
            if (table[index].key == k&&table[index].con == EXIST)
            {
                return &table[index];
            }

            index++;
            if (index>table.size())
            {
                index = 0;
            }
        }
        return NULL;
    }

    bool Erase(const K& pos)
    {
        if (Find(pos) != NULL)
        {
            Find(pos)->con = DELETE;
            size--;
            return true;
        }
        return false;
    }

private:
    void CheckLoadFactor()
    {
        if (table.size() == 0 || (size * 10 / table.size())>7)
        {
            table.size() == 0 ? table.resize(7) : Changecapacity();
        }
    }

    void Changecapacity()
    {
        Hashtable<K, V, __HashFun> newtable;
        newtable.table.resize(GetNextPrime(table.size()));
        for (size_t index = 0; index<table.size(); index++)
        {
            if (table[index].con == EXIST)
            {
                newtable.Insert(table[index].key, table[index].value);
            }
        }
        table.swap(newtable.table);
    }

    size_t GetNextPrime(size_t pre)
    {
        const size_t _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 index = 0; index<_PrimeSize; index++)
        {
            if (pre<_PrimeList[index])
                return _PrimeList[index];
        }
        return _PrimeList[_PrimeSize - 1];
    }

private:
    vector<node> table;
    size_t size;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值