///
#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
collision by chaining的hash的cpp模板实现
最新推荐文章于 2022-06-30 21:16:46 发布