Cpp || 哈希表模拟实现

哈希表的改造

1.模板参数列表的改造
// K:关键码类型
// V: 不同容器V的类型不同,如果是unordered_map,V代表一个键值对,如果是unordered_set,V 为 K
// KeyOfValue: 因为V的类型不同,通过value取key的方式就不同,详细见unordered_map/set的实现
// HF: 哈希函数仿函数对象类型,哈希函数使用除留余数法,需要将Key转换为整形数字才能取模
template<class K, class V, class KeyOfValue, class HF = DefHashF<T> >
class HashTable;
2.增加迭代器操作
template<class K,class V,class KeyOfValue,class HashFun>

struct  Hash_Iterator{
  typedef HashNode<V> Node;
  typedef  Node* pNode;
  typedef Hash_Iterator<K,V,KeyOfValue,HashFun> Self;
  typedef  HashTable<K,V,KeyOfValue,HashFun> HashT;


  pNode _node;
  HashT* _ht; 

  Hash_Iterator(pNode node,HashT* ht)
        :_node(node)
         ,_ht(ht)
      {

      }

      V& operator*(){
        return _node->_data;
      }

      V* operator->(){
        return &(operator*());
      }

      bool operator!=(const Self& it){
        return _node != it._node;
      }

      Self& operator++(){
        if(_node->_next){
          _node=_node->_next;
        }else{
          KeyOfValue Kov;
          size_t index=_ht->HashIndex( Kov(_node->_data),_ht->_table.size() );
          ++index;
          //向后搜索,找到第一个非空链表的头结点,既为下一个元素的位置
          for(;index<_ht->_table.size();++index){
            if(_ht->_table[index]){
              _node= _ht->_table[index];
              break;
            }
          }

          //如果走到表尾,说明无有效元素存在
          if(index==_ht->_table.size()){
            //未找到非空链表
            _node=nullptr;
          }
        }
        return *this;
      }  
 };
3.增加通过key获取value操作
size_t HashIndex(const K& key,size_t sz){
  //把key转换成整数
  HashFun hfun;
  return hfun(key)%sz;
}

哈希表的模拟实现(hash.hpp)

#pragma once
#include<iostream>
#include<vector>
using namespace std;


  template <class V>
    struct HashNode{
      HashNode<V>* _next;
      V _data;

      HashNode(const V& data)
        :_next(nullptr)
         ,_data(data)
      {

      }
    };

  //前置声明,声明函数
template<class K,class V,class KeyOfValue,class HashFun>
class HashTable;

template<class K,class V,class KeyOfValue,class HashFun>

struct  Hash_Iterator{
  typedef HashNode<V> Node;
  typedef  Node* pNode;
  typedef Hash_Iterator<K,V,KeyOfValue,HashFun> Self;
  typedef  HashTable<K,V,KeyOfValue,HashFun> HashT;


  pNode _node;
  HashT* _ht; 

  Hash_Iterator(pNode node,HashT* ht)
        :_node(node)
         ,_ht(ht)
      {

      }

      V& operator*(){
        return _node->_data;
      }

      V* operator->(){
        return &(operator*());
      }

      bool operator!=(const Self& it){
        return _node != it._node;
      }

      Self& operator++(){
        if(_node->_next){
          _node=_node->_next;
        }else{
          KeyOfValue Kov;
          size_t index=_ht->HashIndex( Kov(_node->_data),_ht->_table.size() );
          ++index;
          //向后搜索,找到第一个非空链表的头结点,既为下一个元素的位置
          for(;index<_ht->_table.size();++index){
            if(_ht->_table[index]){
              _node= _ht->_table[index];
              break;
            }
          }

          //如果走到表尾,说明无有效元素存在
          if(index==_ht->_table.size()){
            //未找到非空链表
            _node=nullptr;
          }
        }
        return *this;
      }  
 };

 template <class K,class V,class KeyOfValue,class HashFun>
 class HashTable{
   public:
        typedef HashNode<V> Node;
        typedef Node* pNode;
       //泛型友元声明
        //template <class K,class V,class KeyOfValue>
        //使用上述模板方式会和HashTable模板命名冲突
        template<class Key,class  Val,class  SKeyOfValue,class SHashFun>
        friend struct Hash_Iterator;

        typedef Hash_Iterator<K,V,KeyOfValue, HashFun> Iterator;

   
   public:
        Iterator begin(){
          for(size_t i=0;i<_table.size();++i){
            if(_table[i]){
              return Iterator(_table[i],this);
            }
           
          }
          //空表
          return Iterator(nullptr,this);
        }
     
        Iterator end(){
          return Iterator(nullptr,this);
        }
      public:

        //插入
        pair<Iterator,bool> Insert(const V& data){
          CheckCapacity();
          KeyOfValue Kov;
          size_t index=HashIndex(Kov(data),_table.size());

   
          pNode cur=_table[index];
 

          while(cur){
            if(Kov(cur->_data)== Kov(data)){
            //遍历该位置的单链表从而确定有没有重复的key
              return make_pair(Iterator(cur,this),false);
            }
            cur=cur->_next;
          }

          //找到单链表的最后一个结点还没有找到对应的值
          //就对该链表进行头插操作,申请新的结点用来存储该值
          //在头插的过程中,原来的vector中的结点一直在更换.
          
          cur=new Node(data);
          cur->_next=_table[index];
          _table[index]=cur;
          ++_size;
          return make_pair(Iterator(cur,this),true);
        }
        size_t getNextPrime(const size_t prime)
        {
          static const int PRIMECOUNT = 28;
          static const size_t primeList[PRIMECOUNT] =
          {
            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 < PRIMECOUNT; ++i)
          {
            if (primeList[i] > prime)
              return primeList[i];

          }

          return primeList[PRIMECOUNT - 1];
                    
}

void CheckCapacity(){
  if(_size==_table.size()){
    //size_t newC=_table.size()==0?10:2*_table.size();

    size_t newC=getNextPrime(_table.size());
    KeyOfValue Kov;
    vector<pNode> newHt; 
    //新建一个表,将原来表中的元素赋值到新的表中
    newHt.resize(newC);
    for(size_t i=0;i<_table.size();i++){
      pNode cur=_table[i];

      while(cur){
        pNode next=cur->_next;
        //位置要重新计算
        size_t index=HashIndex(Kov(cur->_data),newHt.size());
        //头插
        cur->_next=newHt[index];
        newHt[index]=cur;
        cur=next;
      }
      _table[i]=nullptr;
    }
    //新表和原来的表进行交换
    _table.swap(newHt);
  }
}


Iterator Find(const K& key){
  size_t index=HashIndex(key,_table.size());
  pNode cur=_table[index];
  KeyOfValue kov;
  while(cur){
    if(kov(cur->data)==key)
      return Iterator(cur,this);
  }
  return end();
}

bool Erase(const K& key){
  size_t index=HashIndex(key,_table.size());
  pNode cur=_table[index];
  pNode prev=nullptr;

  KeyOfValue kov;

  while(cur){
    if(kov(cur->_data)==key){
      if(prev){
        prev->_next=cur->_next;
      }
      else 
        //删除的是链表的头结点,更新头结点
        _table[index]=cur->_next;

      delete cur;
      --_size;
      return true;
    }
    prev =cur;
    cur=cur->_next; 
  }
  return false;
}

size_t HashIndex(const K& key,size_t sz){
  //把key转换成整数
  HashFun hfun;
  return hfun(key)%sz;
}
private:
       vector<pNode> _table;
       size_t _size=0;
    };
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值