哈希表的构造之开链法

来源:互联网 发布:网络信息许可证 编辑:程序博客网 时间:2024/05/02 00:47
前面总体介绍了一下有关哈希算法(哈希表如何构造,怎样减少哈希冲突等)
http://blog.csdn.net/qq_29503203/article/details/52992810

今天主要来实现一下哈希表的构造之开链法,这种方法可以将负载因子延伸到1,即_size==_tables.size(),这样对空间的利用率提高了许多,首先来看一下它的原理:



下面是代码实现:

template<class K>struct GetKType{size_t operator()(const K& key){return key;}};template<>struct GetKType<string>      //模板的特化{//字符串哈希算法(将字符串转为整型)static size_t BKDRHash(const char* str)  //BKDRHash算法{unsigned int seed= 131;// 31 131 1313 13131 131313unsigned int hash= 0;while(*str){hash=hash*seed+(*str++);}return(hash& 0x7FFFFFFF);}size_t operator()(const string& str){return BKDRHash(str.c_str());}};template<class K,class V>struct HashListNode{HashListNode<K,V>* _next;K _key;V _value;HashListNode(const K& key,const V& value):_key(key),_value(value),_next(NULL){}};template<class K,class V,class HashFunc=GetKType<K> >class HashList{typedef HashListNode<K,V> Node;public:HashList():_size(0){_tables.resize(_GetNextPrime(0));}~HashList(){if(_tables.empty())return;for(size_t i=0;i<_tables.size();++i){Node* cur=_tables[i];while(cur){Node* tmp=cur;cur=cur->_next;delete tmp;tmp=NULL;}}_size=0;_tables.clear();}bool Insert(const K& key,const V& value){_CheckSize();size_t index=_HashFunc(key,_tables.size());//先检查该元素是否已在表中了Node* cur=_tables[index];while(cur){if(cur->_key==key)return false;cur=cur->_next;}//采取头插Node* NewNode=new Node(key,value);NewNode->_next=_tables[index];_tables[index]=NewNode;++_size;}bool Find(const K& key){size_t index=_HashFunc(key,_tables.size());Node* cur=_tables[index];    //先定位到在表中哪个位置while(cur){if(cur->_key==key)return true;elsecur=cur->_next;}return false;}bool Remove(const K& key){if(_tables.empty())return false;size_t index=_HashFunc(key,_tables.size());Node* cur=_tables[index];Node* prev=NULL;while(cur){//1.删除头结点//2.删除中间节点及尾节点if(cur->_key==key){if(prev==NULL){_tables[index]=cur->_next;}else{prev->_next=cur->_next;}delete cur;cur=NULL;--_size;return true;}prev=cur;cur=cur->_next;}return false;}void Print()    {        if (_size == 0)            return;        for (size_t i = 0; i < _tables.size(); ++i)        {            Node* cur = _tables[i];            //cout << "_tables[" << i << "]" << "->";printf("_tables[%d]:",i);            while (cur)            {                cout << cur->_key << "->";                cur = cur->_next;            }            cout << "NULL" << endl;        }    }protected:void _Swap(HashList<K,V,HashFunc>& hl){std::swap(hl._tables,_tables);std::swap(hl._size,_size);}size_t _HashFunc(const K& key,size_t size){HashFunc hf;return hf(key)%size;}size_t _GetNextPrime(size_t num){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(num < _PrimeList[i]){return _PrimeList[i];}return _PrimeList[i-1];}return _PrimeList[_PrimeSize-1];   //如果size大于或等于素数表中数据,就返回表中最大数  }void _CheckSize(){if(_size >= _tables.size())      //负载因子为1就开始扩容{size_t NewSize=_GetNextPrime(_tables.size());//通过原表中的数据算出在新表中的位置vector<Node*> newTables;      //出了这个作用域就销毁newTables.resize(NewSize);for(size_t i=0;i<_tables.size();++i){Node* cur=_tables[i];while(cur){Node* tmp=cur->_next;cur=cur->_next;size_t index=_HashFunc(tmp->_key,newTables.size());newTables[index]=tmp;   }}_tables.swap(newTables);}}protected:vector<Node*> _tables;size_t _size;};


0 0