欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

哈希表---开链法解决哈希冲突

发布时间:2023/12/31 46 豆豆
生活随笔 收集整理的这篇文章主要介绍了 哈希表---开链法解决哈希冲突 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

上篇文章已经写过构造哈希表时用开放定址法解决哈希冲突,这次我就来写写这个开链法解决哈希冲突的问题!

一、结点定义

我们已经知道开链法大概是一种什么结构了,(如果不知道,这里有讲哦点我点我)显而易见,实现哈希桶的话我们就必须多一个指针next,至少这样才看起来有个链表的样子嘛!!

[cpp] view plaincopy
  • //开链法(哈希桶)  
  • template<class K,class V>  
  • struct KVNode  
  • {  
  •     K _key;  
  •     V _value;  
  •     KVNode<K,V>* _next;  
  •   
  •     KVNode(const K& key,const V& value)  
  •         :_key(key)  
  •         ,_value(value)  
  •         ,_next(NULL)  
  •     {}  
  • };  
  • 二、哈希表的实现----Inser、Find、Remove

    以数组int a[] = {51, 105, 52, 3, 55, 2, 106, 53, 0}为例

    Insert:

    老规矩,我们还是得判断这个key在表中是否存在,如果存在就插入失败;当两个key有相同的散列地址时,我们只需将前一个结点的next指针指向新结点即可!那么,我们在同一个散列地上的链表进行插入结点时,用头插好还是尾插好呢?!当然是头插好了,这样我们就不用每次遍历到链表的尾结点,这可省了不少事儿!!

    以上面这个数组为例,假设51和105分别都已经插入在正确的位置(此时表长53),接下来需要插入52,我们利用头插进行插入


    如果表中的某个位置此时为NULL,当要进行插入时,做法与上述一样。

    [cpp] view plaincopy
  • bool Insert(const K& key,const V& value)  
  •     {  
  •   
  •         if (Find(key))  //已经存在这个数  
  •             return false;  
  •       
  •         _CheckSize();  
  •         size_t index = _HashFunc(key,_table.size());  
  •         Node* tmp = new Node(key,value);  
  •         tmp->_next = _table[index];  
  •         _table[index] = tmp;  
  •         _size++;  
  •         return true;  
  •     }  

  • Find:

    首先要找到key的散列地址,再在这个地址上挂着的链表开始遍历查找,直到找到相同的key为止。

    [cpp] view plaincopy
  • Node* Find(const K& key)  
  •     {  
  •         if (_size == 0)  
  •             return NULL;  
  •   
  •         size_t index = _HashFunc(key,_table.size());  
  •         Node* cur = _table[index];  
  •         while (cur)  
  •         {  
  •             if (cur->_key == key)  
  •                 return cur;  
  •   
  •             cur = cur->_next;  
  •         }  
  •   
  •         //没有找到  
  •         return false;  
  •     }  
  • Delete:

    删除一个数据时就是要删除这个结点,删除结点的方式与删除链表一个结点的方式是一样的,只要改变前一个结点的next指针。不过在这之前我们需要通过散列地址找到这个结点。假如要删除53表示的这个结点


    [cpp] view plaincopy
  • bool Remove(const K& key)  
  •     {  
  •         if(_size == 0)  
  •             return false;  
  •   
  •         size_t index = _HashFunc(key,_table.size());  
  •         Node* cur = _table[index];  
  •         Node* prev = NULL;  
  •         while (cur)  
  •         {  
  •             while(cur->_key == key)  
  •             {  
  •                 //删除的是头(第一个)结点  
  •                 if (prev == NULL)  
  •                 {  
  •                     _table[index] = cur->_next;  
  •                 }  
  •                 //删除非头结点(中间或后边)  
  •                 else  
  •                 {  
  •                     prev->_next = cur->_next;  
  •                 }  
  •   
  •                 delete cur;  
  •                 _size--;  
  •                 return true;  
  •             }  
  •             prev = cur;  
  •             cur = cur->_next;  
  •         }  
  •         return false;  
  •     }  

  • 具体代码:

    [cpp] view plaincopy
  • //开链法(哈希桶)  
  • template<class K,class V>  
  • struct KVNode  
  • {  
  •     K _key;  
  •     V _value;  
  •     KVNode<K,V>* _next;  
  •   
  •     KVNode(const K& key,const V& value)  
  •         :_key(key)  
  •         ,_value(value)  
  •         ,_next(NULL)  
  •     {}  
  • };  
  •   
  • template<class K,class V>  
  • class HashTable  
  • {  
  •     typedef KVNode<K,V> Node;  
  • public:  
  •     HashTable()  
  •         :_size(0)  
  •     {  
  •         _table.resize(3);  
  •     }  
  •     ~HashTable()  
  •     {  
  •         for (size_t i=0; i<_table.size(); ++i)  
  •         {  
  •             Node* cur = _table[i];  
  •             while (cur)  
  •             {  
  •                 Node* tmp = cur->_next;  
  •                 delete cur;  
  •                 cur = tmp;  
  •             }  
  •             _size = 0;  
  •             _table.clear();  
  •         }  
  •     }  
  •   
  •     Node* Find(const K& key);  
  •     bool Remove(const K& key);  
  •     bool Insert(const K& key,const V& value);  
  •     void Display()  
  •     {  
  •         for (size_t i=0; i<_table.size(); ++i)  
  •         {  
  •             printf("Table[%d]->",i);  
  •             Node* cur = _table[i];  
  •             while (cur)  
  •             {  
  •                 Node* next = cur->_next;  
  •                 cout<<cur->_key<<" ";  
  •                 cur = next;  
  •             }  
  •             cout<<NULL;  
  •             cout<<endl;  
  •         }  
  •     }  
  • protected:  
  •     void _CheckSize()  
  •     {  
  •         if (_table.size() == 0 || _size == _table.size())  
  •         {  
  •             vector<Node*> tmpTable;  
  •             tmpTable.resize(_GetPrimer(_table.size()));  
  •             //将原表_table中的结点直接放入新表中  
  •             for (size_t i=0; i<_table.size(); ++i)  
  •             {  
  •                 Node* cur = _table[i];  
  •                 while (cur)  
  •                 {  
  •                     Node* next = cur->_next;  
  •   
  •                     size_t index = _HashFunc(cur->_key,tmpTable.size());  
  •                     cur->_next = tmpTable[index];  
  •                     tmpTable[index] = cur;  
  •   
  •                     cur = next;  
  •                 }  
  •             }  
  •             _table.swap(tmpTable);  
  •         }  
  •     }  
  •   
  •     size_t _GetPrimer(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];  
  •             }  
  •         }  
  •     }  
  •     size_t _HashFunc(const K& key,size_t size)  
  •     {  
  •         return key%size;  
  •     }  
  • protected:  
  •     vector<Node*> _table;  
  •     size_t _size;   //已有的数据个数  
  • };  
  • 总结

    以上是生活随笔为你收集整理的哈希表---开链法解决哈希冲突的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。