collision by chaining的hash的cpp模板实现

///
#ifndef _HASHTBL_H
#define _HASHTBL_H


using namespace std;


///

//常用的Hash函数
/*
 * 字符串Hash,采用通用处理方式
 *
*/
inline unsigned long long str2hash(const char *str)   //不管多长的字符串,都按每个字符是32进制中的一位来处理,例如,字符串“abcd”的hash值为 32^3*a+32^2*b+32*c+d
{ 
    register unsigned long long h; 
    register unsigned char *p; 
 
    for(h=0, p = (unsigned char *)str; *p ; p++) 
        h = 31 * h + *p; 
    return h; 
} 

//Hash表模板
template<class KT,class VT>
class THashTbl
{
public:
    THashTbl();
    virtual ~THashTbl();
public:
    typedef VT*  valuePtr;
    struct HashNode                     //当发生冲突时,用链表来实现hash, 所有key冲突的entry 依次放在链的末尾
    {
        VT     _value;
        KT       _key;
        HashNode*   _pNext;
        HashNode(){_pNext = NULL;}
    };
public:
    //重置Hash 表大小
    void resize(int iSize);
    
    //删除Hash 表
    void clear();
    
    //根据键值查找
    valuePtr find(KT key);
    
    //插入或修改
    VT& operator[](KT key);
    
    //插入或修改
    VT& insert(KT key, const VT& value);
    
    //Hash表桶大小
    int size() {return m_iSize;}
protected:
    HashNode *   m_pHash;   //       Hash数组,为了快速存取,用数组来直接index
    int                m_iSize;     //数组长度
};
///
#define   HASH_KEY(x)    (x%(m_iSize))

template<class KT,class VT>
THashTbl<KT,VT>::THashTbl()
{
    m_pHash = NULL;
    m_iSize   = 0;
}

template<class KT,class VT>
THashTbl<KT,VT>::~THashTbl()
{
    clear();
}

template<class KT,class VT>
void THashTbl<KT,VT>::clear()
{
    if(m_pHash != NULL)
    {
        HashNode *pNode, *pPre;
        for(int i=0; i<m_iSize; i++)
        {
            //删除每个Hash 节点串
            pNode=m_pHash[i]._pNext;
            while(pNode != NULL)
            {
                pPre=pNode;
                pNode=pNode->_pNext;
                delete pPre;
            }
        }
        delete[] m_pHash;
    }
    m_iSize=0;
    m_pHash=NULL;
}
template<class KT,class VT>
void THashTbl<KT,VT>::resize(int iSize) // 初始化时要调用该功能,指定hash表的大小,用连续的数组来存,目的就是为了存取快速
{
    if(iSize < 1)
        return;
    clear();
    m_pHash = new HashNode[iSize];
    m_iSize = iSize;
}

template<class KT,class VT>
typename THashTbl<KT,VT>::valuePtr THashTbl<KT,VT>::find(KT key)  // 沿着链表查找key,返回value的指针
{
    unsigned long long tempKey = (unsigned long long)(key);
    if(tempKey<0)
    {
        return NULL;
    }
    HashNode *pNode = m_pHash[HASH_KEY(tempKey)]._pNext;
    while(pNode != NULL)
    { 
        if(pNode->_key == key)
        {
            return &(pNode->_value);
        }
        pNode=pNode->_pNext;
    }
    return NULL;
}

template<class KT,class VT>
typename THashTbl<KT,VT>::VT&  THashTbl<KT,VT>::insert(KT key, const VT& value)  //往hash表中插入元素,如果发生冲突,顺着链表找,在链表的末尾插入<key,val>键值对
{
    unsigned long long tempKey = (unsigned long long)(key);  // 长整型的hash值
    HashNode *pNode = m_pHash[HASH_KEY(tempKey)]._pNext; 
    HashNode *pPre = &m_pHash[HASH_KEY(tempKey)];
    while(pNode != NULL)  //如果已经存在这个key了,则该处的next指针肯定不为null,在冲突链表的末尾插入新的
    {
        if(pNode->_key == key)         //如果要插入的<key,val>对的key已经存在了,就更新val,这个不是hash的功能,而是map的特性,
        {
            pNode->_value = value;
            return (pNode->_value); // 返回
        }
        pPre=pNode;
        pNode=pNode->_pNext;
    }
    //TraceOut("key:%s\n",key);
    pNode = new HashNode;
    pNode->_key = key;
    pNode->_value = value;
    pPre->_pNext = pNode;
    return (pNode->_value);
}

template<class KT,class VT>
typename THashTbl<KT,VT>::VT&  THashTbl<KT,VT>::operator[](KT key) //重载【】运算符
{
    valuePtr ptr = find(key); 
    if (ptr!= NULL)
    return *ptr;
    return insert(key, VT());
}
///
#endif //_HASHTBL_H


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值