在第一个版本上修改完善的,可以任意使用,但请尊重原创:
#ifndef QUICK_HASH_H
#define QUICK_HASH_H
#include <cstdio>
#include <cstring>
/**@file QuickHash.h
* 实现Hash功能的模板类
* @author xiaoxing.zhou
* @date 2012-4-26
* @version v2.0
*/
/**@struct
* 定义比较操作
*/
struct Equal
{
static bool equal(int a, int b){return a==b;};
static bool equal(const char* pStr1, const char* pStr2){return strcmp(pStr1,pStr2)==0;};
};
/**@struct
* 定义Hash函数
*/
struct Hash
{
static int hash(int a){return a;}
static int hash(const char* pStr)
{
int b = 378551;
int a = 63689;
int hash = 0;
while (*pStr){
hash = hash * a + (*pStr++);
a *= b;
}
return (hash & 0x7FFFFFFF);
}
};
template<typename Key, typename Value, typename Equal, typename Hash, int Size>class QuickHash;
/**@class
* 定义Hash链表结点
* 结点的键值对不负责删除
*/
template<typename Key, typename Value, typename Equal>
class HashNode
{
public:
typedef HashNode<Key, Value, Equal> Node;
HashNode(const Key& key, const Value& value);
~HashNode();
const Key& GetKey(){return m_key;}
Value& GetValue(){return m_value;}
void SetValue(const Value& value){m_value=value;}
protected:
/**前后结点指针操作*/
void SetPrev(HashNode* pPrev){m_pPrev=pPrev;}
void SetNext(HashNode* pNext){m_pNext=pNext;}
Node* PrevNode(){return m_pPrev;}
Node* NextNode(){return m_pNext;}
/**前后结点插入*/
void FrontInsert(Node* pNode);
void BackInsert(Node* pNode);
/**结点移除*/
void Remove();
/**交换结点*/
void Swap(Node* pNode);
/**链表操作*/
Node* Find(const Key& key);
bool Adjacent(Node* pNode);
int NextNum();
int PrevNum();
protected:
Node* m_pPrev;
Node* m_pNext;
Key m_key;
Value m_value;//!要求保存的数据可以复制
template<typename Key, typename Value, typename Equal, typename Hash, int Size> friend class QuickHash;
};
template<typename Key, typename Value, typename Equal>
HashNode<Key, Value, Equal>::HashNode(const Key& key, const Value& value)
{
m_key=key;
m_value=value;
m_pPrev=NULL;
m_pNext=NULL;
}
template<typename Key, typename Value, typename Equal>
HashNode<Key, Value, Equal>::~HashNode()
{
/**前向删除结点*/
if(m_pPrev)delete m_pPrev;
/**后向删除结点*/
if(m_pNext)delete m_pNext;
}
/**前插入结点*/
template<typename Key, typename Value, typename Equal>
void HashNode<Key, Value, Equal>::FrontInsert(Node* pNode)
{
pNode->m_pNext=this;
pNode->m_pPrev=m_pPrev;
}
/**后插入结点*/
template<typename Key, typename Value, typename Equal>
void HashNode<Key, Value, Equal>::BackInsert(Node* pNode)
{
pNode->m_pNext=m_pNext;
m_pNext=pNode;
}
/**移除结点*/
template<typename Key, typename Value, typename Equal>
void HashNode<Key, Value, Equal>::Remove()
{
if(m_pPrev){
m_pPrev->m_pNext=m_pNext;
if(m_pNext)m_pNext->m_pPrev=pTemp;
}
else{
m_pNext->m_pPrev=NULL;
}
m_pPrev=NULL;
m_pNext=NULL;
}
/**交换两个结点顺序*/
template<typename Key, typename Value, typename Equal>
void HashNode<Key, Value, Equal>::Swap(Node* pNode)
{
if(pNode && this!=pNode){//!不允许同一结点交换
Node* pTemp=m_pPrev;
pNode->m_pPrev=m_pPrev;
m_pPrev=pTemp;
pTemp=pNode->m_pNext;
pNode->m_pNext=m_pNext;
m_pNext=pTemp;
}
}
/**遍历链表查找结点*/
template<typename Key, typename Value, typename Equal>
typename HashNode<Key,Value,Equal>::Node* HashNode<Key, Value, Equal>::Find(const Key& key)
{
if(Equal::equal(m_key,key))return this;
Node* pTemp=m_pNext;
while(pTemp){
if(Equal::equal(pTemp->m_key,key))return pTemp;
pTemp=pTemp->m_pNext;
}
pTemp=m_pPrev;
while(pTemp){
if(Equal::equal(pTemp->m_key,key))return pTemp;
pTemp=pTemp->m_pPrev;
}
return NULL;
}
/**判断是否相临*/
template<typename Key, typename Value, typename Equal>
bool HashNode<Key, Value, Equal>::Adjacent(Node* pNode)
{
return pNode->m_pNext==this||pNode->m_pPrev=this;
}
/**后续结点个数*/
template<typename Key, typename Value, typename Equal>
int HashNode<Key, Value, Equal>::NextNum()
{
Node* pTemp=m_pNext;
int num=0;
while(pTemp){
++num;
pTemp=pTemp->m_pNext;
}
return num;
}
/**前驱结点个数*/
template<typename Key, typename Value, typename Equal>
int HashNode<Key, Value, Equal>::PrevNum()
{
Node* pTemp=m_pPrev;
int num=0;
while(pTemp){
++num;
pTemp=pTemp->m_pPrev;
}
return num;
}
/**@class
* 定义Hash类
*/
template<typename Key, typename Value, typename Equal, typename Hash, int Size=1000>
class QuickHash
{
public:
typedef HashNode<Key, Value, Equal> Node;
QuickHash();
~QuickHash();
/**扩大表容量*/
void Resize(int size);
/**
* 键值对操作
* 不阻止插入同键值的结点,使用时候需要注意
*/
bool Insert(const Key& key, const Value& value);
bool Delete(const Key& key, const Value& value);
bool Delete(Node* pNode);
/**查找键值对*/
Node* Find(const Key& key);
/**统计信息*/
void Stat();
private:
Node** m_pHashTable;
int m_HashSize;
};
template<typename Key, typename Value, typename Equal, typename Hash, int Size>
QuickHash<Key, Value, Equal, Hash, Size>::QuickHash()
{
m_HashSize=Size;
m_pHashTable=new Node*[m_HashSize];
for(int i=0; i<m_HashSize; ++i){
m_pHashTable[i]=NULL;
}
}
template<typename Key, typename Value, typename Equal, typename Hash, int Size>
QuickHash<Key, Value, Equal, Hash, Size>::~QuickHash()
{
for(int i=0; i<m_HashSize; ++i){
if(m_pHashTable[i])delete m_pHashTable[i];
}
delete[] m_pHashTable;
}
//!扩大尺寸
template<typename Key, typename Value, typename Equal, typename Hash, int Size>
void QuickHash<Key, Value, Equal, Hash, Size>::Resize(int size)
{
if(size>m_HashSize){//!扩大尺寸
Node** pHashTable=new Node[size];
Node* pNode;
Node* pTemp;
int key;
for(int i=0; i<m_HashSize; ++i){
pNode=m_pHashTable[i];
if(pNode){
key=Hash::hash(pNode->GetKey())%size;
pTemp=pHashTable[key];
if(pTemp){
pTemp->FrontInsert(pNode);
}
else pHashTable[key]=pNode;
}
}
delete[] m_pHashTable;
m_pHashTable=pHashTable;
m_HashSize=size;
}
}
//!插入键值对
template<typename Key, typename Value, typename Equal, typename Hash, int Size>
bool QuickHash<Key, Value, Equal, Hash, Size>::Insert(const Key& key, const Value& value)
{
int index=Hash::hash(key)%m_HashSize;
if(index<0&&index>=m_HashSize)return false;
Node* pNode=m_pHashTable[index];
Node* pNew=new Node(key,value);
if(pNode)pNode->BackInsert(pNew);
else m_pHashTable[index]=pNew;
return true;
}
//!删除键值对
template<typename Key, typename Value, typename Equal, typename Hash, int Size>
bool QuickHash<Key, Value, Equal, Hash, Size>::Delete(const Key& key, const Value& value)
{
int index=Hash::hash(key)%m_HashSize;
if(index<0&&index>=m_HashSize)return false;
Node* pNode=m_pHashTable[index];
Node* pFind;
if(pNode&&pFind=pNode->Find(key)){
if(pFind==pNode){
pNode=pNode->NextNode();
pFind->Remove();
m_pHashTable[index]=pNode;
}
else pFind->Remove();
delete pFind;
return true;
}
return false;
}
//!删除结点
template<typename Key, typename Value, typename Equal, typename Hash, int Size>
bool QuickHash<Key, Value, Equal, Hash, Size>::Delete(Node* pNode)
{
int index=Hash::hash(pNode->GetKey())%m_HashSize;
if(index<0&&index>=m_HashSize)return false;
Node* pTemp=m_pHashTable[index];
if(pTemp&&pTemp==pNode){//!避免删除头结点
Node* pNext=pNode->NextNode();
pNode->Remove();
delete pNode;
m_pHashTable[index]=pNext;
return true;
}
else{
pNode->Remove();
delete pNode;
return true;
}
return false;
}
/**查找结点*/
template<typename Key, typename Value, typename Equal, typename Hash, int Size>
typename QuickHash<Key, Value, Equal, Hash, Size>::Node* QuickHash<Key, Value, Equal, Hash, Size>::Find(const Key& key)
{
int index=Hash::hash(key)%m_HashSize;
if(index<0&&index>=m_HashSize)return false;
Node* pNode=m_pHashTable[index];
Node* pFind;
if(pNode&&(pFind=pNode->Find(key))){
return pFind;
}
return NULL;
}
/**统计冲突个数*/
template<typename Key, typename Value, typename Equal, typename Hash, int Size>
void QuickHash<Key, Value, Equal, Hash, Size>::Stat()
{
int count=0;
int times=0;
Node* pNode;
for(int i=0; i<m_HashSize; ++i){
pNode=m_pHashTable[i];
if(pNode){
++count;
count+=pNode->NextNum();
++times;
}
}
printf("collision rate:%.2f cover rate:%.2f%%\n",(count/(double)times),(100*times/(double)m_HashSize));
}
#endif