本程序可以将test.txt文件中的记录按key值存储,然后可以快速查找。原理就像数组下表定位一样,只不过,哈希定位是通过key来定位,这个key是通过哈希函数计算得到的,是一个唯一的值。当然有时会得到重复的key值,那么这是就得解决冲突,典型算法是:用线性补偿探测处理冲突,并处理表溢出。如下面的语句。
k = 0;
do {
l = (l+17) % m;
} while(ht[l]!="" && ++k<=ht.size());
if (ht[l] == "")
ht[l]= name;
else
if (k>ht.size()) {
cout << "哈希表溢出!" << endl;
overflowBucket.push_back(name);
}
do {
l = (l+17) % m;
} while(ht[l]!="" && ++k<=ht.size());
if (ht[l] == "")
ht[l]= name;
else
if (k>ht.size()) {
cout << "哈希表溢出!" << endl;
overflowBucket.push_back(name);
}
完整源码如下:
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#include
#include
#include
#include
#include
#include
using namespace std;
#ifdef WIN32
#define TEST_FILE "d:\\work\\proc\\stl\\stl01\\test.txt"
#else
#define TEST_FILE "/tmp/test.txt"
#endif
#define TEST_FILE "d:\\work\\proc\\stl\\stl01\\test.txt"
#else
#define TEST_FILE "/tmp/test.txt"
#endif
class hashvector
{
private:
vectorht;
vectoroverflowbucket;
size_t n;
size_t m;
public:
hashvector(vectornamelist,int mo);
// 返回表长
size_t size() const { return m; }
// 返回表大小
size_t table_size() const { return n; }
// 返回装填因子
float load_factor() const { return float(table_size())/size(); }
// 哈希表插入操作
void insert(vector& ht,
vector& overflowBucket, string name);
// 哈希表查找操作
void search(string name);
// 输出表
void print_table();
private:
size_t mid(size_t s);
size_t hstr(const string& name);
};
hashvector::hashvector(vectornamelist,int m0):m(m0)
{
n=namelist.size();
ht.resize(m);
for(size_t i=0;i<n;i++)
{
insert(ht,overflowbucket,namelist[i]);
}
}
// 首先将参数s平方,然后取其各位数字并保存到数组a,最后返回第4、5位数
size_t hashvector::mid(size_t s)
{
int i=0, a[10];
size_t d = 1, s0;
s0 = s*s;
while(s0>d) d *= 10;
d /= 10;
while(d != 0) {
a[i++] = s0/d;
s0 = s0%d;
d = d/10;
}
return (a[3]*10+a[4]);
}
size_t hashvector::hstr(const string& name)
{
// 累加name的ASCII码
size_t sum = 0, j = 0;
while(j<name.size()) {
sum += name[j]; j++;
}
return sum;
}
void hashvector::insert(vector& ht,
vector& overflowBucket, string name)
{
size_t k, s, l;
// 用除留余数法构造哈希函数
s = hstr(name); // 见7.4.2字符串哈希函数
l = mid(s) % m; // 除留余数法计算模块
if (ht[l]=="")
ht[l] = name;
else {
// 用线性补偿探测处理冲突,并处理表溢出
k = 0;
do {
l = (l+17) % m;
} while(ht[l]!="" && ++k<=ht.size());
if (ht[l] == "")
ht[l]= name;
else
if (k>ht.size()) {
cout << "哈希表溢出!" << endl;
overflowBucket.push_back(name);
}
}
}
// 在哈希表中查找指定的姓名
void hashvector::search(string name)
{
size_t l;
bool found = false;
// 计算哈希函数
size_t s = hstr(name);
l = mid(s) % m;
if (ht[l]==name) {
cout << name << "已找到!在" << l << "号纪录\n";
found = true;
}
int k = 0;
while (ht[l]!=name && ht[l]!="" && ++k<=ht.size()) {
// 线性补偿探测
l = (l+17) % m;
if (ht[l]==name && !found) {
cout << name << "已找到!在" << l << "号纪录\n";
found = true;
break;
}
}
if(k>ht.size())
for (size_t i=0; i<overflowbucket.size(); i++)
if(overflowbucket[i]==name) {
cout << name << "已找到!在溢出桶" << i << "号纪录\n";
found = true;
break;
}
if (!found)
cout << name << "未找到!\n";
}
void hashvector::print_table()
{
// 显示建立的哈希表
size_t j, l;
cout << "************************** 当前哈希表 *************************\n";
cout << " 编号 列信息\n";
// j = 0;
for (l=0; l<m; l++)="" {
if (ht[l] != "") {
cout << setw(4) << l << setw(25) << ht[l] << "\t";
// j++;
//if ((j+1) % 3==1)
cout << endl;
}
}
cout << "\n总人数是: " << table_size() << endl;
cout << size() << " 个槽已被占用\n" ;
cout << "装填因子是: " << load_factor() << endl;
}
int main(void)
{
vectornamelist;
ifstream ifs(TEST_FILE);
if (!ifs)
{
cerr<<"error open file!"<<endl;
getchar();
exit(0);
}
int n=35;
int cnt=0;
string name;
//string name2;
while(ifs>>name && cnt++<n)
{
namelist.push_back(name);
//namelist.push_back(name2);
}
ifs.close();
hashvector table(namelist,57);
{
n=namelist.size();
ht.resize(m);
for(size_t i=0;i<n;i++)
{
insert(ht,overflowbucket,namelist[i]);
}
}
// 首先将参数s平方,然后取其各位数字并保存到数组a,最后返回第4、5位数
size_t hashvector::mid(size_t s)
{
int i=0, a[10];
size_t d = 1, s0;
s0 = s*s;
while(s0>d) d *= 10;
d /= 10;
while(d != 0) {
a[i++] = s0/d;
s0 = s0%d;
d = d/10;
}
return (a[3]*10+a[4]);
}
size_t hashvector::hstr(const string& name)
{
// 累加name的ASCII码
size_t sum = 0, j = 0;
while(j<name.size()) {
sum += name[j]; j++;
}
return sum;
}
void hashvector::insert(vector& ht,
vector& overflowBucket, string name)
{
size_t k, s, l;
// 用除留余数法构造哈希函数
s = hstr(name); // 见7.4.2字符串哈希函数
l = mid(s) % m; // 除留余数法计算模块
if (ht[l]=="")
ht[l] = name;
else {
// 用线性补偿探测处理冲突,并处理表溢出
k = 0;
do {
l = (l+17) % m;
} while(ht[l]!="" && ++k<=ht.size());
if (ht[l] == "")
ht[l]= name;
else
if (k>ht.size()) {
cout << "哈希表溢出!" << endl;
overflowBucket.push_back(name);
}
}
}
// 在哈希表中查找指定的姓名
void hashvector::search(string name)
{
size_t l;
bool found = false;
// 计算哈希函数
size_t s = hstr(name);
l = mid(s) % m;
if (ht[l]==name) {
cout << name << "已找到!在" << l << "号纪录\n";
found = true;
}
int k = 0;
while (ht[l]!=name && ht[l]!="" && ++k<=ht.size()) {
// 线性补偿探测
l = (l+17) % m;
if (ht[l]==name && !found) {
cout << name << "已找到!在" << l << "号纪录\n";
found = true;
break;
}
}
if(k>ht.size())
for (size_t i=0; i<overflowbucket.size(); i++)
if(overflowbucket[i]==name) {
cout << name << "已找到!在溢出桶" << i << "号纪录\n";
found = true;
break;
}
if (!found)
cout << name << "未找到!\n";
}
void hashvector::print_table()
{
// 显示建立的哈希表
size_t j, l;
cout << "************************** 当前哈希表 *************************\n";
cout << " 编号 列信息\n";
// j = 0;
for (l=0; l<m; l++)="" {
if (ht[l] != "") {
cout << setw(4) << l << setw(25) << ht[l] << "\t";
// j++;
//if ((j+1) % 3==1)
cout << endl;
}
}
cout << "\n总人数是: " << table_size() << endl;
cout << size() << " 个槽已被占用\n" ;
cout << "装填因子是: " << load_factor() << endl;
}
int main(void)
{
vectornamelist;
ifstream ifs(TEST_FILE);
if (!ifs)
{
cerr<<"error open file!"<<endl;
getchar();
exit(0);
}
int n=35;
int cnt=0;
string name;
//string name2;
while(ifs>>name && cnt++<n)
{
namelist.push_back(name);
//namelist.push_back(name2);
}
ifs.close();
hashvector table(namelist,57);
table.print_table();
name="hhhh";
table.search(name);
getchar();
return 0;
}