哈希表的封装

/*哈希函数的比较测试
 *
 *author:FLT
 *finish:2014.4.13
 */

#include <iostream>
#include <fstream>
#include <string>
#define HashMaxSize 9997
using namespace std;

template <class T>
struct ElemType
{
	T key;
};

template <class T>
struct HashLink
{
	ElemType<T> data;
	HashLink<T> *link;
};
//--------------------哈希表类定义---------------
template <class T>
class HSearch
{
public:
	HSearch();
	~HSearch();
	void CreatHash(int kind);           //创建hash表
	void DisplayHash();         //输出哈希表
	bool Insert_Hash(ElemType<T> data, int kind);  //元素插入
	//bool Delete_Hash(ElemType<T> data);  //元素删除
	int Search_Hash(T key);    //哈希查找
	double backet_usage();     //计算桶的使用率
	double avg_backet_len();   //计算平均桶长
	unsigned int GetCount() { return count; }
	unsigned int GetAW() { return AllWord; }
	//--------------------------------------------
	int Hash(T key);           //哈希函数
	int BKDRHash(T key); 
	unsigned int ELFHash(T key);
	unsigned int APHash(T key);
	unsigned int ZJHash(T key);  //根据编程珠玑中的思想设计的hash函数
	//--------------------------------------------
private:
	HashLink<T> * HashTable[HashMaxSize];  
	unsigned int count;              //记录存入哈希表中不同单词的数目
	unsigned int AllWord;
};

template <class T>
HSearch<T>::HSearch()
{
	for (int i=0; i<HashMaxSize; ++i)
	{
		HashTable[i] = new HashLink<T>;
		HashTable[i]->data.key = '\0';
		HashTable[i]->link = NULL;
	}
	count = 0;
	AllWord = 0;
};
template <class T>
HSearch<T>::~HSearch()
{
	HashLink<T> *p, *q;
	for (int i=0; i<HashMaxSize; ++i)
	{
		p = HashTable[i];
		q = HashTable[i]->link;
		delete HashTable[i];
		while(q)
		{
			p = q;
			q = q ->link;
			delete p;
		}
	}
	count = 0;
	AllWord = 0;
};
template <class T>
void HSearch<T>::CreatHash(int kind)
{
	ifstream ifs("OLLMAN.txt");
	char read[40];
	ElemType<T> data;
	while(ifs.getline(read, 40, ' ')) // 逐词读取方法三
	{
		int len = strlen(read);
		char temp[40];
		int k = 0;
		for (int i = 0; i<len; ++i)
		{   //除去标点符号
			if( (65 <= read[i] && read[i] <= 90) || (97 <= read[i] && read[i] <= 122 ))
			{
				temp[k++] = read[i];
			}
		}
		temp[k] = '\0';
		//printf("%s\n", temp);
		data.key = temp;	
		AllWord++;
		Insert_Hash(data, kind);
	}
	//DisplayHash();
}
template <class T>
void HSearch<T>::DisplayHash()
{
	for (int i=0; i<HashMaxSize; ++i)
	{
		cout<<"HashTable["<<i<<"]:->";
		HashLink<T> *p, *q;
		p = HashTable[i];
		q = HashTable[i]->link;
		while(q)
		{
			cout<< q->data.key <<"->";
			p = q;
			q = q->link;
		}
		cout<<"^"<<endl;
	}
}

//----------------将元素插入哈希表中-------------------------
template <class T>
bool HSearch<T>::Insert_Hash(ElemType<T> data, int kind)
{
	int index;
	HashLink<T> *p, *pre, *s;
	s = new HashLink<T>;
	s->data = data;
	s->link = NULL;
	switch(kind)
	{
	case 1:index = Hash(data.key) % HashMaxSize;break;
	case 2:index = BKDRHash(data.key) % HashMaxSize; break;
	case 3:index = ELFHash(data.key) % HashMaxSize; break;
	case 4:index = APHash(data.key) % HashMaxSize; break;
	case 5:index = ZJHash(data.key) % HashMaxSize; break;
	default:index = Hash(data.key) % HashMaxSize;break;
	}
	pre = HashTable[index];
	p = pre->link;
	while (p)
	{
		if (p->data.key == data.key)
		{
			//cout <<"该元素已存在,插入失败!"<<endl;
			return false;
		}
		else {
			pre = p;
			p = p->link;
		}
	}
	pre->link = s;
	count++;
	return true;
}

//---------------------桶的使用率和已使用桶的平均桶长----------
template <class T>
double HSearch<T>::backet_usage()
{
	int use = 0;
	for (int i=0; i<HashMaxSize; ++i)
	{
		if (NULL != HashTable[i]->link)
			use++;
	}
	return (use*1.0)/HashMaxSize;
}
template <class T>
double HSearch<T>::avg_backet_len()
{
	int use = 0;
	for (int i=0; i<HashMaxSize; ++i)
	{
		if (NULL != HashTable[i]->link)
			use++;
	}
	return (count *1.0) / (use*1.0) ;
}
//-----------------哈希函数----------------------------------
template <class T>
int HSearch<T>::Hash(T key)
{
	int hash = 0;
	int i=0;
	while(key[i] != '\0')
	{
		hash += key[i];
		++i;
	}
	return hash ; //除留余数法
}
// ---------------------BKDR Hash Function---------------------------
template <class T>
int HSearch<T>::BKDRHash(T key)
{
    int seed = 131; // 31 131 1313 13131 131313 etc..
    int hash = 0;
	int i = 0;
    while (key[i] != '\0')
    {
        hash = hash * seed + key[i];
		++i;
    }
    return (hash & 0x7FFFFFFF);
}
// ---------------------ELF Hash Function---------------------------
template <class T>
unsigned int HSearch<T>::ELFHash(T key)
{
    unsigned int hash = 0;
    unsigned int x    = 0;
	int i = 0;
    while (key[i] != '\0')
    {
        hash = (hash << 4) + (key[i++]);
        if ((x = hash & 0xF0000000L) != 0)
        {
            hash ^= (x >> 24);
            hash &= ~x;
        }
    }
	
    return (hash & 0x7FFFFFFF);
}
// ---------------------AP Hash Function---------------------
template <class T>
unsigned int HSearch<T>::APHash(T key)
{
    unsigned int hash = 0;
    int i;
    for (i=0; key[i] != '\0'; i++)
    {
        if ((i & 1) == 0)
        {
            hash ^= ((hash << 7) ^ (key[i++]) ^ (hash >> 3));
        }
        else
        {
            hash ^= (~((hash << 11) ^ (key[i++]) ^ (hash >> 5)));
        }
    }
    return (hash & 0x7FFFFFFF);
}
// ---------------------编程珠玑中的哈希函数---------------------
template <class T>
unsigned int HSearch<T>::ZJHash(T key)
{
    unsigned int h = 0;
    for (int i=0; key[i] != '\0'; i++)
        h = 31 *h + key[i]; //31为质数
    return h;
}

#include "HashSearch.h"
	
int main()
{
	cout<<"================哈希函数的比较=====================\n";
	for (int i=1; i<=5; ++i)
	{
		HSearch<string> hs;
		hs.CreatHash(i);
		if(i == 1) {
			cout <<"建立的Hash表单词总数为:"<<hs.GetAW()<<endl;
			cout <<"哈希表长度为:"<<HashMaxSize<<endl<<endl;
		}
		switch(i)
		{
		case 1:cout<<"------------------除留余数法-----------------------"<<endl;break;
		case 2:cout<<"-------------------BKDR Hash-----------------------"<<endl;break;
		case 3:cout<<"----------------- --ELF Hash-----------------------"<<endl;break;
		case 4:cout<<"---------------------AP Hash-----------------------"<<endl;break;
		case 5:cout<<"--------------编程珠玑中的哈希函数-----------------"<<endl;break;
		default:break;
		}
		cout <<"桶的使用率为:"<<hs.backet_usage()<<endl;
    	cout <<"已使用桶的平均长度为:"<<hs.avg_backet_len()<<endl;
	}
	system("pause");
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值