C++ Hash表设计V2.0

在第一个版本上修改完善的,可以任意使用,但请尊重原创:

#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



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值