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.线性探测

wKioL1dNZMiCn7i3AABDOIfnoms902.jpg-wh_50

#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.二次探测

wKiom1dNY-LCUsFVAABtoZOO1f8479.jpg-wh_50

#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.哈希桶法

wKiom1dNZATDns6WAABdrvUUhVU953.jpg-wh_50

#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;
};