实验四 哈希表设计
一、实验目的
理解哈希表实现机制,掌握哈希函数的构造方法和冲突处理方法,实现哈希表
上的查找、插入和删除操作。
二、实验内容
(1)、对于给定20个人的姓名,用除留余数法构造哈希函数,用线性探测再散列
法处理冲突,构造哈希表;
(2)、对于给定的一个姓名,在哈希表上进行查找,如果其存在则将其删除,否
则将其插入到该哈希表上。
三、实验原理、方法和手段
实现查找的最基本技术是比较,如果能够建立记录的关键字与其存储地址之间
的之间对应,然后以0次或尽可能少的比较次数完成查找,将大大提高算法的效率,
这正是哈希表为查找思想的出发点。
对于给定的若干条记录,以关键字为自变量按照某种方式构造Hash函数,对应
的函数值作为该记录的存储地址。显然,一般而言,很难构造出单的Hash函数,即
存在关键字不同、对应的Hash函数值却相同的现象,称之为冲突,并称这两个关键
字为同义词。对于冲突现象,需要采用合适的机制予以解决。
不妨设字母(不分大小写)a~z对应于数值1~26,对于给定的20个姓名作为关键
字,将构成每个姓名的首字母对应的数值相加,然后按照除留余数法构造哈希函数,
并用线性探测再散列法处理冲突,完成哈希表的构造。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
const int TABLE_SIZE = 50; // 可以调整这个值以减少冲突
class HashTable {
private:
vector<string> table;
int hashFunction(string key) {
int sum = 0;
for (char ch : key) {
sum += tolower(ch) - 'a' + 1; // 计算字母的数值之和
}
return sum % TABLE_SIZE;
}
public:
HashTable() : table(TABLE_SIZE, "") {}
void insert(string key) {
int index = hashFunction(key);
while (!table[index].empty()) {
index = (index + 1) % TABLE_SIZE; // 线性探测再散列
}
table[index] = key;
}
bool find(string key) {
int index = hashFunction(key);
int start = index;
do {
if (table[index] == key) {
return true; // 找到关键字
}
index = (index + 1) % TABLE_SIZE;
} while (!table[index].empty() && index != start); // 防止无限循环
return false;
}
void remove(string key) {
if (!find(key)) {
cout << key << " not found." << endl;
return;
}
int index = hashFunction(key);
while (table[index] != key) {
index = (index + 1) % TABLE_SIZE;
}
table[index] = ""; // 删除关键字
cout << key << " removed." << endl;
}
void display() {
for (int i = 0; i < TABLE_SIZE; ++i) {
if (!table[i].empty()) {
cout << i << ": " << table[i] << endl;
}
}
}
};
int main() {
HashTable ht;
// 插入姓名
ht.insert("Alice");
ht.insert("Bob");
ht.insert("Coco");
ht.insert("Jite");
ht.insert("Rios");
ht.insert("Liqiang");
ht.insert("Liutianlei");
ht.insert("Gewangjun");
ht.insert("Qiaobusi");
ht.insert("Buluke");
ht.insert("Shinubi");
ht.insert("Leijun");
ht.insert("Mahuateng");
ht.insert("Mayun");
ht.insert("Zengyi");
ht.insert("Linghua");
ht.insert("Zhaosi");
ht.insert("Xubo");
ht.insert("Zhoushuyi");
ht.insert("Falao");
// ... 添加其他姓名
// 显示哈希表
ht.display();
// 查找和删除和插入
string name = "Alice";
if (ht.find(name)) {
ht.remove(name);
}
else {
ht.insert(name);
}
// 显示更新后的哈希表
ht.display();
return 0;
}
结果:
实验结果分析:
- 这个程序示例展示了如何使用哈希表来存储和管理数据(这里是姓名)。
- 它实现了基本的哈希表操作,如插入、查找和删除,同时使用了除留余数法和线性探测再散列法来处理哈希冲突。
- `TABLE_SIZE` 是哈希表的大小,可以根据需要进行调整。表的大小会影响冲突的频率和查找效率。
思考题
最理想的Hash函数应该具有什么特征?
1均匀性
2确定性
3高效性
4快速计算
5抗碰撞性
6安全性
7适应性
8输出范围的可调性
9无法逆向
0难以预测