/*哈希函数的比较测试
*
*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;
}