哈希表是记录的存储位置和关键字之间建立的一种映射关系,这个映射关系就是hash函数.
1:构建hash函数的方法:
- 直接定植法:
- 平方取中法
- 除留余数法
- 折叠法
- 随机数法
在构建hash函数的时候,会存在关键字不一样,但是记录会是一样的情况.key1≠key2,但是f(key1)=f(key2),这里的f就是哈希函数.这种现象就是冲突.
解决这种冲突有如下办法:
- 开放定址法(线性探测法)
- 再散列函数法
- 链地址法
- 公共溢出区法
下面建立一个用hash查找,删除,增加的字典程序.便于在实际使用中对词典进行更新.
建立hash函数的方法是除留余数法
解决冲突的方法是线性探测法.
如下是简单的cpp代码.
#include <iostream>
#include <fstream>
#include <string>
#include <sstream> //getline 包含在 sstream 中,要include!
using namespace std;
// 该工程是创建词典,查询词典
#define LEN 8 //中文字长度,中文字拼音长度 (中:zh ong1,声韵母结构)
#define READ_NUM 4 // 每个中文汉字最多有4种读音
#define SUM_LEN LEN*READ_NUM
#define SUCCESS 1
#define FAILED -1
#define TABLE_LEN 1024 //散列表长度
struct word{
char cwrd[LEN];
char phn[SUM_LEN];
int isExist;
};
class myHashTable{
public:
myHashTable();
~myHashTable();
void init();
bool loadDict(const char* dictFn);
int getHashAddr(const char* mwrd);
void updateDict(const char* mwrd);
void deleteWord(const char* mwrd);
void searchDict(const char* mwrd);
void logDict();
void saveDict(const char* outFn);
void getStdinStr(string &mstr);
private:
struct word mcwrd[TABLE_LEN];
}wrdHashTable;
myHashTable::myHashTable()
{
init();
}
myHashTable::~myHashTable()
{
}
void myHashTable::init(void)
{
memset(mcwrd,0,sizeof(*mcwrd)*TABLE_LEN);
}
/*
* 从当前的词典中加载进来
*/
bool myHashTable::loadDict(const char* dictFn)
{
ifstream fin;
fin.open(dictFn,ios::in);
string rdLine = "";
if(!fin.is_open())
{
cout <<"open " << dictFn << " failed" <<endl;
return false;
}
else
{
while(!getline(fin,rdLine))
{
//TODO
}
}
fin.close();
return true;
}
/*
* 获取hash地址,以单字建立hash函数
*/
int myHashTable::getHashAddr(const char* mwrd)
{
int n = strlen(mwrd);
if(n == 0)
return FAILED;
int a = 0, ichar = 0;
for(int i = 0; i < n;++i)
{
ichar = mwrd[i];
if(ichar < 0)
ichar = -ichar;
a += ichar;
}
return a%TABLE_LEN; //除留余数法
}
void myHashTable::getStdinStr(string &mstr)
{
mstr.clear();
getline(cin,mstr);
fflush(stdin);
}
/*
* 更新字典
*/
void myHashTable::updateDict(const char* mwrd)
{
int n = getHashAddr(mwrd);
string s = "";
while(mcwrd[n].isExist)
n++;
memset(mcwrd[n].cwrd,0,sizeof(*mcwrd[n].cwrd)*LEN);
strcpy(mcwrd[n].cwrd,mwrd);
cout << "请输入该字的拼音:" << endl;
getStdinStr(s);
strcpy(mcwrd[n].phn,s.c_str());
fflush(stdin);
mcwrd[n].isExist = 1;
return ;
}
/*
* 删除某个字
*/
void myHashTable::deleteWord(const char* mwrd)
{
int addr = getHashAddr(mwrd);
string s;
for(int i = 0;i < TABLE_LEN;++i)
{
s = (string)mcwrd[addr].cwrd;
if((s.compare(mwrd) == 0) &&(mcwrd[addr].isExist))
{
mcwrd[addr].isExist = 0;
return;
}
addr++;
if(addr == TABLE_LEN)
addr = 0;
}
cout <<"该字不存在字典中"<<endl;
}
/*
* 查字典
*/
void myHashTable::searchDict(const char* mwrd)
{
int addr = getHashAddr(mwrd);
string s;
for(int i = 0;i < TABLE_LEN;++i)
{
s = (string)mcwrd[addr].cwrd;
if((s.compare(mwrd) == 0) &&(mcwrd[addr].isExist))
{
cout << mcwrd[addr].cwrd << "\t" << mcwrd[addr].phn<< endl;
return ;
}
addr++;
if(addr == TABLE_LEN)
addr = 0;
}
cout <<"checkDict:" << "该字不存在字典中" << endl;
}
/*
* 打印字典
*/
void myHashTable::logDict(void)
{
for(int i = 0; i < TABLE_LEN; ++i)
{
if(mcwrd[i].isExist)
cout << mcwrd[i].cwrd << "\t" << mcwrd[i].phn << "\t" << i << endl;
}
}
/*
* 保存词典
*/
void myHashTable::saveDict(const char* outFn)
{
fstream fout;
fout.open(outFn,ios::out);
if(fout.is_open())
{
for(int i = 0; i < TABLE_LEN; ++i)
{
if(mcwrd[i].isExist)
cout << mcwrd[i].cwrd << "\t" << mcwrd[i].phn << endl;
}
fout.close();
}
else
cout <<"open " <<outFn << " failed" << endl;
}
void menu() //菜单
{
cout<<"菜单:"<<endl;
cout<<"1.添加"<<endl;
cout<<"2.查找"<<endl;
cout<<"3.删除记录"<<endl;
cout<<"4.显示字典"<<endl;
cout<<"5.储存字典"<<endl;
cout<<"6.退出系统"<<endl;
}
int main(void)
{
myHashTable mHashTable;
//int x;
string wrd = "";
string x = "";
while(1)
{
menu();
//cin>>x;
//cout << x << endl;
getline(cin,x);
cout << x << endl;
//if (x<1 || x>5)
//{
// cout<<"请从新输入:"<<endl;
// cin>>x;
//}
if (x=="1")
{
cout<<"请输入新字:"<<endl;
mHashTable.getStdinStr(wrd);
mHashTable.updateDict(wrd.c_str());
}
if(x=="2")
{
cout<<"请输入你要查找的字:"<<endl;
mHashTable.getStdinStr(wrd);
cout<<"输出查找的信息:"<<endl;
mHashTable.searchDict(wrd.c_str());
}
if(x=="3")
{
cout<<"请输入要删除的字:"<<endl;
mHashTable.getStdinStr(wrd);
mHashTable.deleteWord(wrd.c_str());
cout<<"记录已删除!"<<endl;
}
if(x=="4")
{
cout<<"显示所有记录:"<<endl;
mHashTable.logDict();
}
if(x=="5")
{
cout<<"通信录已保存:"<<endl;
mHashTable.saveDict("./new.dct");
}
if(x=="6")
return 0;
fflush(stdin);
}
}