哈希算法(一次探测,二次探测,哈希桶法)支持字典查询

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了哈希算法(一次探测,二次探测,哈希桶法)支持字典查询相关的知识,希望对你有一定的参考价值。

        HashTable-散列表/哈希表,是根据关键字(key)而直接访问在内存存储位置的数据结构。它通过一个关键值的函数将所需的数据映射到表中的位置来访问数据,这个映射函数叫做散列函数,存放记录的数组叫做散列表。

构造哈希表的几种方法

  1. 直接定址法--取关键字的某个线性函数为散列地址,Hash(Key)= Key 或 Hash(Key)= A*Key + B,A、B为常数。

  2. 除留余数法--取关键值被某个不大于散列表长m的数p除后的所得的余数为散列地址。Hash(Key)= Key % P。

  3. 平方取中法

  4. 折叠法

  5. 随机数法

  6. 数学分析法

  • 哈希冲突/哈希碰撞

不同的Key值经过哈希函数Hash(Key)处理以后可能产生相同的值哈希地址,我们称这种情况为哈希冲突。任意的散列函数都不能避免产生冲突。

  • 处理哈希冲突的闭散列方法

1.线性探测

技术分享

#pragma once
#include<iostream>
using namespace std;
#include<string>
namespace First
{
enum State
{
    EMPTY,
    DELETE,
    EXIST,
    
};
template<class k>
class HashTable
{
public:
    HashTable(size_t capacity = 10)
        :_table(new k[capacity])
        ,_state(new State[capacity])
        ,_size(0)
        ,_capacity(capacity)
    {
        //memset(_state,EMPTY,sizeof((State*_capacity )));//不可以是这种情况,memset是以字节,enum类型,默认从上到下分别是012...
         for(size_t i=0; i< capacity;i++)
        {
            _state[i]=EMPTY;
        }
    }
    HashTable( HashTable<k>& ht)
        :_table(NULL)
        ,_state(NULL)
        ,_size(0)
    {
        HashTable<k> tmp(ht._capacity);
        for(size_t i=0;i < tmp._capacity; ++i)
        {
            if(ht._state[i] == EXIST)
            {
                tmp.Insert(ht._table[i]);
            }
        }
        swap(_size,ht._size );
        swap(_capacity ,ht._capacity );
        swap(_table,ht._table );
        swap(_state,ht._state );
    }
    HashTable<k>& operator = (HashTable<k> ht)
    {
        swap(_size,ht._size );
        swap(_capacity ,ht._capacity );
        swap(_table,ht._table );
        swap(_state,ht._state );
        return *this;
    }
    ~HashTable()
    {
        delete [] _table;
    }
    bool Insert(const k& key)
    {
        _CheckCapacity();    
        size_t index = HashFunc(key);
        size_t start = index;
        while(_state[index] == EXIST)
        {
            ++index;
            if(index == _capacity)
            {
                index = 0;
            }
            if(start ==index)
            {
                return false;
            }
        }
        _table[index] = key;
        _state[index] = EXIST;
        ++_size;
        return true;
    }
    bool Find(const k& key)
    {
        size_t index = HashFunc(key);
        size_t start = index;
        while(_table[index] != EMPTY)
        {
            if(_table[index] == key)
            {
                if(_state[index] == DELETE)
                {
                    return true;
                }
                if(index == _capacity)
                {
                    index = 0;
                }
                if(start == index)
                {
                    return false;
                }
                return true;
            }
            return false;
        }
        return true;
    }
    bool Remove(const k& key)
    {
        size_t index = HashFunc(key);
        size_t start = index;
        while(_state[index] == EXIST)
        {
            if(_table[index] == key)
            {
                _state[index] = DELETE;
                --_size;
                return true;
            }
            ++index;
            if(index == _capacity )
            {
                index = 0;
            }
            if(index == start)
            {
                return false;
            }
            
        }
        return false;
    }
    size_t HashFunc(const k& key)
    {
        return key%_capacity;    
    }
    void Print()
    {
        for(size_t i=0;i<_capacity ;i++)
        {
            cout<<"[state,value]:"<<_state[i]<<","<<_table[i]<<endl;
        }
    }
protected :
    void _CheckCapacity()
    {
        if(_size*10/_capacity >= 7)
        {
            HashTable<k> tmp(2*_capacity);
            for(size_t i=0;i<_capacity ;++i)
            {
                if(_state[i] == EXIST)
                {
                    tmp.Insert(_table[i]);
                }
                swap(tmp._capacity ,_capacity );
                swap(tmp._size ,_size);
            }
        }
    }
protected:
    k* _table;
    State* _state;
    size_t _size;
    size_t _capacity;
};
void Test1()
{
    HashTable<int> ht;

    ht.Insert(89);
    ht.Insert(18);
    ht.Insert(49);
    ht.Insert(58);
    ht.Insert(9);
    ht.Print();
    cout<<"------"<<endl;
    ht.Remove(9);
    ht.Print();
}
void Test2()
{
    HashTable<int> ht;
    ht.Insert(89);
    ht.Insert(18);
    ht.Insert(49);
    ht.Insert(58);
    ht.Insert(9);
    HashTable<int> ht1;
    ht1= ht;
    ht1.Print ();
}
}

2.二次探测

技术分享

#pragma once
#include<iostream>
using namespace std;
#include<string>
enum State
{
    EMPTY,
    DELETE,
    EXIST,
};
//类型转换

template<class k,class v>
struct kv
{
    k _key;
    v _value;
    kv(const k& key=k(),const v& value=v())
        :_key(key)
        ,_value(value)
    {}
};
template<class k>
struct __HashFunc
{
    size_t operator() (const k&key)
    {
        return key;
    }
};
template<>
struct __HashFunc<string>
{
    size_t operator()(const string& key)
    {
        size_t hash = 0;
        for(size_t i=0;i<key.size();++i)
        {
            hash += key[i];
        }
        return hash;
    }
};
template<class k,class v>
class HashTable
{
    typedef HashTable<k,v> Table;
public:
    HashTable()
    {}
    HashTable(size_t capacity)
        :_table(new kv<k,v>[capacity])
        ,_capacity(capacity)
        ,_size(0)
        ,_state(new State[capacity])
    {
        for(size_t i=0;i<_capacity;++i)
        {
            _state[i] = EMPTY;
        }
    }
    ~HashTable()
    {
        if(_table)
          delete [] _table;
        if(_state)
          delete _state;
          _size = 0;
          _capacity = 0;
    }
    HashTable(const Table& hb)
        :_table(new Table[hb._capacity ])
        ,_capacity(hb._capacity )
        ,_size(0)
        ,_state(new state[hb._capacity])
    {
        for(i=0;i<_capacity;++i)
        {
            _state[i] = EMPTY;
        }
        for (int i = 0; i < _capacity; ++i)
        {
            if (hb._state[i] == EXIST)
            {
                this->Insert(hb._table[i]._key,hb._table[i]._value);
            }
        }
    }
    Table& operator = (Table ht)
    {
        this->_swap(ht);
        return *this;
    }
    bool Insert(const k& key,const v& value)
    {
        _CheckCapacity(key);
        size_t index = HashFunc(key);
        size_t start = index;
        do
        {
            if (_state[index] != EXIST)
                break;
            if (_state[index] == EXIST && _table[index]._key == key)
                return true;
            ++index;
            if (index == _capacity)
                index = 0;
        } while (index != start);
        if (_state[index] == EXIST)//一般不会出现
            return false;
        _table[index] = kv<k,v>(key, value);
        _state[index] = EXIST;
        ++_size;
        return true;
    }
    kv<k,v>* Find(const k&key)
    {
        size_t index = HashFunc(key);
        size_t start = index;
        for(size_t i=0;i<_capacity;++i)
        {
            if(_table[index]._key == key)
            {
                return &(_table[index]);
            }
            index = index+i*i;
            if(index = _capacity)
            {
                index = 0;
            }
            if(index == start)
            {
                return false;
            }
            ++i;
        }
    }
    void print()
    {
        for(size_t i = 0;i<_capacity;++i)
        {
            cout<<"[key "<<_table[i]._key<<"";
            cout<<" value "<<_table[i]._value<<"]";
            cout<<"state:%d"<<_state[i]<<endl;
            cout<<endl;
        }
        cout<<endl;
    }
    void Remove(const k& key)
    {
        size_t index = HashFunc(key);
        size_t begin = index;
        do
        {
            if (_state[index] == EMPTY)
                break;
            if (_state[index] == EXIST&&_table[index]._key == key)
            {
                _state[index] = DELETE;
                --_size;
            }
            ++index;
            if (index == _capacity)
                index = 0;
        } while (index != begin);
    }
protected:
    void _CheckCapacity(const k& key)
    {
        if(_size*10 /_capacity >= 7)
        {
            HashTable<k,v> tmp(_capacity * 2+1);
            for(size_t i=0;i<_capacity ;++i) 
            {
                if(_state[i]==EXIST)
                {
                    tmp.Insert(_table[i]._key,_table[i]._value);
                }
                
            }
           this->_swap(tmp);
        }

    }
    size_t HashFunc(const k& key)
    {
        __HashFunc<k> Ha;
        return Ha(key)%_capacity;
    }
    void _swap(Table& hs)
    {
        swap(_table, hs._table);
        swap(_capacity, hs._capacity);
        swap(_size, hs._size);
        swap(_state, hs._state);
    }
protected:
    kv<k,v>* _table;
    State* _state;
    size_t _size;
    size_t _capacity;
};
void Test1()
{
        HashTable<int, int> hs(5);
        hs.Insert(1, 1);
        hs.Insert(2, 2);
        hs.Insert(1, 3);
        hs.Insert(3, 1);
        hs.Insert(4, 4);
        hs.Insert(10, 4);//扩容测试
        hs.print();
        kv<int, int>* ret = hs.Find(1);
        if (ret)
            cout << "Find(1)" << ret->_value << endl;
        ret = hs.Find(5);
        if (ret)
            cout << "Find(5)" << ret->_value << endl;
        hs.Remove(1);
        ret = hs.Find(1);
        if (ret)
            cout << "Find(1)" << ret->_value << endl;
        hs.print();
}
void Test2()
{
        HashTable<string, string> hs(5);
        hs.Insert("Sunday" ,"7*");
        hs.Insert("Monday" ,"8*");
        hs.Insert("Tuesday" ,"9*");
        hs.Insert("Wednesday", "10*");
        hs.Insert("Thursday", "11*");
        hs.Insert("Firday", "12*");//扩容测试
        hs.print();
    //    kv<int, string>* ret = hs.Find(1);

}#pragma once
#include<iostream>
using namespace std;
#include<string>
enum State
{
    EMPTY,
    DELETE,
    EXIST,
};
//类型转换

template<class k,class v>
struct kv
{
    k _key;
    v _value;
    kv(const k& key=k(),const v& value=v())
        :_key(key)
        ,_value(value)
    {}
};
template<class k>
struct __HashFunc
{
    size_t operator() (const k&key)
    {
        return key;
    }
};
template<>
struct __HashFunc<string>
{
    size_t operator()(const string& key)
    {
        size_t hash = 0;
        for(size_t i=0;i<key.size();++i)
        {
            hash += key[i];
        }
        return hash;
    }
};
template<class k,class v>
class HashTable
{
    typedef HashTable<k,v> Table;
public:
    HashTable()
    {}
    HashTable(size_t capacity)
        :_table(new kv<k,v>[capacity])
        ,_capacity(capacity)
        ,_size(0)
        ,_state(new State[capacity])
    {
        for(size_t i=0;i<_capacity;++i)
        {
            _state[i] = EMPTY;
        }
    }
    ~HashTable()
    {
        if(_table)
          delete [] _table;
        if(_state)
          delete _state;
          _size = 0;
          _capacity = 0;
    }
    HashTable(const Table& hb)
        :_table(new Table[hb._capacity ])
        ,_capacity(hb._capacity )
        ,_size(0)
        ,_state(new state[hb._capacity])
    {
        for(i=0;i<_capacity;++i)
        {
            _state[i] = EMPTY;
        }
        for (int i = 0; i < _capacity; ++i)
        {
            if (hb._state[i] == EXIST)
            {
                this->Insert(hb._table[i]._key,hb._table[i]._value);
            }
        }
    }
    Table& operator = (Table ht)
    {
        this->_swap(ht);
        return *this;
    }
    bool Insert(const k& key,const v& value)
    {
        _CheckCapacity(key);
        size_t index = HashFunc(key);
        size_t start = index;
        do
        {
            if (_state[index] != EXIST)
                break;
            if (_state[index] == EXIST && _table[index]._key == key)
                return true;
            ++index;
            if (index == _capacity)
                index = 0;
        } while (index != start);
        if (_state[index] == EXIST)//一般不会出现
            return false;
        _table[index] = kv<k,v>(key, value);
        _state[index] = EXIST;
        ++_size;
        return true;
    }
    kv<k,v>* Find(const k&key)
    {
        size_t index = HashFunc(key);
        size_t start = index;
        for(size_t i=0;i<_capacity;++i)
        {
            if(_table[index]._key == key)
            {
                return &(_table[index]);
            }
            index = index+i*i;
            if(index = _capacity)
            {
                index = 0;
            }
            if(index == start)
            {
                return false;
            }
            ++i;
        }
    }
    void print()
    {
        for(size_t i = 0;i<_capacity;++i)
        {
            cout<<"[key "<<_table[i]._key<<"";
            cout<<" value "<<_table[i]._value<<"]";
            cout<<"state:%d"<<_state[i]<<endl;
            cout<<endl;
        }
        cout<<endl;
    }
    void Remove(const k& key)
    {
        size_t index = HashFunc(key);
        size_t begin = index;
        do
        {
            if (_state[index] == EMPTY)
                break;
            if (_state[index] == EXIST&&_table[index]._key == key)
            {
                _state[index] = DELETE;
                --_size;
            }
            ++index;
            if (index == _capacity)
                index = 0;
        } while (index != begin);
    }
protected:
    void _CheckCapacity(const k& key)
    {
        if(_size*10 /_capacity >= 7)
        {
            HashTable<k,v> tmp(_capacity * 2+1);
            for(size_t i=0;i<_capacity ;++i) 
            {
                if(_state[i]==EXIST)
                {
                    tmp.Insert(_table[i]._key,_table[i]._value);
                }
                
            }
           this->_swap(tmp);
        }

    }
    size_t HashFunc(const k& key)
    {
        __HashFunc<k> Ha;
        return Ha(key)%_capacity;
    }
    void _swap(Table& hs)
    {
        swap(_table, hs._table);
        swap(_capacity, hs._capacity);
        swap(_size, hs._size);
        swap(_state, hs._state);
    }
protected:
    kv<k,v>* _table;
    State* _state;
    size_t _size;
    size_t _capacity;
};
void Test1()
{
        HashTable<int, int> hs(5);
        hs.Insert(1, 1);
        hs.Insert(2, 2);
        hs.Insert(1, 3);
        hs.Insert(3, 1);
        hs.Insert(4, 4);
        hs.Insert(10, 4);//扩容测试
        hs.print();
        kv<int, int>* ret = hs.Find(1);
        if (ret)
            cout << "Find(1)" << ret->_value << endl;
        ret = hs.Find(5);
        if (ret)
            cout << "Find(5)" << ret->_value << endl;
        hs.Remove(1);
        ret = hs.Find(1);
        if (ret)
            cout << "Find(1)" << ret->_value << endl;
        hs.print();
}
void Test2()
{
        HashTable<string, string> hs(5);
        hs.Insert("Sunday" ,"7*");
        hs.Insert("Monday" ,"8*");
        hs.Insert("Tuesday" ,"9*");
        hs.Insert("Wednesday", "10*");
        hs.Insert("Thursday", "11*");
        hs.Insert("Firday", "12*");//扩容测试
        hs.print();
    //    kv<int, string>* ret = hs.Find(1);

}

3.哈希桶法

技术分享

#include<vector>
#pragma once
#include<iostream>
#include<string>
using namespace std;
template<class k,class v>
struct HashTableNode
{
    k _key;
    v _value;
    HashTableNode<k,v>* _next;
    HashTableNode(const k& key,const v& value)
        :_key(key)
        ,_value(value)
        ,_next(NULL)
    {}
};
template<class k>
struct __HashFunc
{
    size_t operator() (const k&key)
    {
        return key;
    }
};
template<>
struct __HashFunc<string>
{
    size_t operator()(const string& key)
    {
        size_t hash = 0;
        for(size_t i=0;i<key.size();++i)
        {
            hash += key[i];
        }
        return hash;
    }
};
template <class k,class v,class HashFunc = __HashFunc<k> >
class HashTable
{
public:
    HashTable()
        :_table(NULL)
        ,_size(0)
    {}
    HashTable(size_t capacity)
        :_size(0)
    {
        _table.resize(_CheckCapacity());
    }
    ~HashTable()
    {
        for(size_t i=0;i<_table.size();++i)
        {
            HashTableNode<k,v>* cur = _table[i];//_table[i]重命名为cur
            while(cur)
            {
                HashTableNode<k,v>* del = cur;
                cur = cur->_next ;     //每次使cur为它的下一个
                delete del;
            }
            _table[i] = NULL;
        }
    }
    HashTable(const HashTable<k,v> & ht)
        :_size(0)
    {
        _table.resize(ht._table.size());
        for(size_t i = 0;i<ht._table.size();++i)
        {
            HashTableNode<k,v>* cur = ht._table[i];
            while(cur)
            {
                Insert(cur->_key ,cur->_value);
                cur = cur->_next ;
            }
        }
    }
    //赋值
    HashTable<k,v>  &operator = ( HashTable<k,v>& ht )
    {
        if(this != &ht)
        {
            HashTable<k,v> tmp(ht);
            _table.swap(tmp._table);
            swap(_size,tmp._size);
        }
        return *this;
    }
public:
    bool Insert(const k& key,const v& value)
    {
        _CheckCapacity();
        size_t index = _HashFunc(key,_table.size());
        HashTableNode<k,v>* cur = _table[index];
        while(cur)
        {
            if(cur->_key == key)
            {
                return false;
            }
            cur = cur->_next ;
        }
        HashTableNode<k,v>* tmp = new HashTableNode<k,v> (key,value);
        tmp->_next = _table[index];
        _table[index] = tmp;
        ++_size;
        return true;
    }
    HashTableNode<k,v>* Find(const k& key)
    {
        size_t index = _HashFunc(key,_table.size());
        HashTableNode<k,v>* cur = _table[index];
        while(cur)
        {
            if(cur->_key == key)
            {
                return cur;
            }
            cur = cur->_next ;
        }
        return NULL;
    }
    bool Remove(const k& key)
    {
        size_t index = _HashFunc(key,_table.size());
        HashTableNode<k,v>* cur = _table[index];
        HashTableNode<k,v>* prev = NULL;
        HashTableNode<k,v>* del = NULL;
        if(cur->_key == key)
        {
            del = cur;
            _table[index] = cur->_next ;
            delete del;
            return true;
        }
        prev = cur;
        cur = cur->_next ;
        while(cur)
        {
            if(cur->_key == key)
            {
                del = cur;
                prev->_next = cur->_next ;
                delete del;
                return true;
            }
            prev = cur;
            cur = cur->_next ;
        }
        return false;
    }
    void Print()
    {
        for(size_t i = 0;i<_table.size();++i)
        {
            printf("_table[%d]:",i);
            HashTableNode<k,v>* cur = _table[i];
            while(cur)
            {
                cout<<"["<<cur->_key <<","<<cur->_value <<"]"<<"->";
                cur = cur->_next ;
            }
            cout<<"NULL"<<endl;
        }
    }
protected:
    size_t _HashFunc(const k& key,size_t capacity)
    {
        HashFunc  hash;
        return hash(key) % capacity;
    }
    size_t _GetNetPrime(const 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(_PrimeList[i]>_size)
            {
                return _PrimeList[i];
            }
        }
        return _PrimeList[_PrimeSize - 1];
    }

    void _CheckCapacity()
    {
        if(_size == _table.size())
        {
            size_t nextPrime = _GetNetPrime(_size);
            vector<HashTableNode<k,v>* > nextTable;
            nextTable.resize(nextPrime);
            for(size_t i=0;i<_table.size();++i)
            {
                HashTableNode<k,v>* cur = _table[i];
                while(cur)
                {
                    HashTableNode<k,v>* tmp = cur;
                    cur = cur->_next;
                    //在新表中相应的位置,头插
                    size_t index = _HashFunc(tmp->_key ,nextPrime);
                    nextTable[index] = tmp;
                }
                _table[i] = NULL; 
            }
            _table.swap(nextTable);
        }
    }
protected:
    vector <HashTableNode<k,v>* > _table;
    size_t _size;
};









以上是关于哈希算法(一次探测,二次探测,哈希桶法)支持字典查询的主要内容,如果未能解决你的问题,请参考以下文章

哈希表

字典与哈希表(HashMap)

哈希表解决冲突法(二次探测)

DS哈希查找—二次探测再散列

问题 B: DS哈希查找—二次探测再散列(关键字互不相同)

哈希表(散列表)二次探测