数据结构之散列表的实现

  1. 之前研究STL源码的时候发现哈希Table底层是实现看起来实现的非常的简洁,觉得自己去写一个哈希表肯定也是很简单的。但是,但是,但是我今天看了一下数据结构里面的哈希表的简单实现,才发现其实也是有很多学问在里面的,所以今天就打算自己实现一下,做一个记录,方便以后自己来查看学习。
  2. 因为哈希表是会产生哈希冲突的嘛,一般的解决方法都是采用开链法,所以今天就简单的实现一个开链法的具体步骤。
  3. 具体步骤
    1.   先是写一个简单的模板类的框架
      #include <iostream>
      #include <list>
      #include <vector>
      #include <string.h>
      using namespace std;
      template <typename Object>
      class HashTable{
      public:
          explicit HashTable(int hashsize = 101);
      
          bool constains(const Object & x)const;
      
          void makeEmpty();
          void insert(const Object & x);
          void remove(const Object & x);
      
      private:
          int CurrentSize;
          vector < list<Object> > theLists;//这个是vector加上list的格式
      
          void ReHash();
          int MyHash (const Obeject & a) const;
      };
      int hash (const string & x);
      int hash (int key);

       这个框架还是比较通俗的,但是由于编辑工具不是很好用(linux下面的编辑工具有点bug,老是闪退,我就么有建工程,将就看吧)。主要就是实现了一下插入,删除,包含核哈希函数的构造这几个简单的方法。下面是这几个函数的具体实现代码。

    2.     void ReHash(){
      
          }
          int MyHash (const Obeject & a) const{
              int hashval = hash(x);
      
              hashval %= theLists.size();
              if (hashval < 0)
                  hashval += theLists.size();
              return hashval;
          }
      
              void makeEmpty(){
              for ( int i = 0; i< theLists.size(); i++)
                  theLists[i].clear();
          }
          bool insert(const Object & x){
              list<Object> &list1 = theLists[ MyHash(x) ];
              if (find ((list1.begin(), list1.end(), x) != list1.end()))
                  return false;
      
              list1.push_back(x);
              if (++CurrentSize > theLists.size())
                  ReHash();
              return true;
          }
          bool remove(const Object & x){
              /*移除就是找到了对应的*/
              list<Object> &list1 = theLists[ MyHash(x) ];
              list<Object> ::iterator iter = find (list1.begin(), list1.end(), x);
      
              if ( iter == list1.end() )
                  return false;
      
              list1.erase(iter);
              --CurrentSize;
              return true;
          }
              bool constains(const Object & x)const{
              /*这个就是相当于找到了对应的链表,再去链表中找到对应的实值*/
              const list<Object> &list1 = theLists[ MyHash(x) ];
              return find ((list1.begin(), list1.end(), x) != list1.end())
          }

       这个就是实现简单的带有链表和vector的哈希表了,这个比较常见。

    3.   当然还有不使用链表的哈希表。
      1.   这样的链表的解决冲突的方式有许多种
        1.   线性探测,根据键值,调用哈希函数找到对应的键值,如果该位置已经满了,就依次向后移动一个位置,知道找到末尾还是满了,就从头部开始向后找起,直到找到一个空的可以插入的位置。
        2.   平方探测,这个和上面类似,但是它每次移动的位置是当前移动次数的平方倍数。这个随机性比较大。
        3.   关于这一类的哈希表的实现我自己感觉应该是比上面的那种简单些,实现方式大多是类似的。最主要的还是去检测当前位置是否满,然后移动的规则的一些算法。

    4.   STL中的散列表还有一些其他类型的。比如hash_set,hash_map;感兴趣可以去看些STL源码。
原文地址:https://www.cnblogs.com/Kobe10/p/6066368.html