线性探测再散列 建立HASH表
要求:根据数据元素的关键字和哈希函数建立哈希表并初始化哈希表,用开放定址法处理冲突,按屏幕输出的功能表选择所需的功能实现用哈希表对数据元素的插入,显示,查找,删除。
初始化哈希表时把elem[MAXSIZE]、elemflag[MAXSIZE]和count分别置0。创建哈希表时按哈希函数创建哈希表,输入数据元素的关键字时,以“0”结束输入且要求关键字为正整数,数据元素个数不允许超过表长MAXSIZE。
输出的形式:根据所选择的哈希表的功能输出相应提示语句和正确结果。
程序的功能:将一组个数不超过哈希表长度的数据元素,按其关键字和哈希函数存入哈希表中,如果产生冲突用开放定址法处理并找出相应的地址。能实现用哈希表对数据元素的插入,显示,查找,删除。
测试数据:maxsize=10
哈希函数:H(key)=key%7
处理冲突方法:开放定址法 Hi=(H(key)+di)%13 i=1,2,3,…,9
哈希表又称散列表。哈希表存储的基本思想是:以数据表中的每个记录的关键字 k为自变量,通过一种函数H(k)计算出函数值。把这个值解释为一块连续存储空间(即数组空间)的单元地址(即下标),将该记录存储到这个单元中。在此称该函数H为哈希函数或散列函数。按这种方法建立的表称为哈希表或散列表。
处理冲突的方法:
开放寻址法:Hi=(H(key) + di) MOD m, i=1,2,…, k(k<=m-1),其中H(key)为散列函数,m为散列表长,di为增量序列,可有下列三种取法:
1.di=1,2,3,…, m-1,称线性探测再散列;
2.di=1^2, (-1)^2, 2^2,(-2)^2, (3)^2, …, ±(k)^2,(k<=m/2)称二次探测再散列;
3.di=伪随机数序列,称伪随机探测再散列。
再散列法:Hi=RHi(key), i=1,2,…,k. RHi均是不同的散列函数,即在同义词产生地址冲突时计算另一个散列函数地址,直到冲突不再发生,这种方法不易产生“聚集”,但增加了计算时间;
链地址法(拉链法):将所有关键字为同义词的记录存储在同一线性链表中;
建立一个公共溢出区。
#include <iostream> #include <math.h> #include <stdio.h> #include <stdlib.h> #define MAXSIZE 10 #define SUCCESS 1 #define UNSUCCESS 0 using namespace std; typedef struct { int elem[MAXSIZE]; int elemflag[MAXSIZE]; int count; } HashTable; void InitialHash(HashTable &H) /*哈希表初始化*/ { int i; H.count = 0; for (i = 0; i < MAXSIZE; i++) { H.elem[i] = 0; H.elemflag[i] = 0; } } int Hash(int kn) /*哈希函数H(key)=key MOD 7*/ { return (kn % 7); } int SearchHash(HashTable &H, int k) /*查找关键字为k的元素*/ { int t, s; s = t = Hash(k); xun: if (H.elem[t] == k && H.elemflag[t] == 1) return SUCCESS; else if (H.elem[t] != k && H.elemflag[t] == 1) { t = (t + 1) % MAXSIZE; goto xun; } else return UNSUCCESS; } int InsertHash(HashTable &H, int e) /*插入元素e*/ { int p; p = Hash(e); if (SearchHash(H, e)) { cout << "已有此数!" << endl; return UNSUCCESS; } else { H.elemflag[p] = 1; H.elem[p] = e; H.count++; return SUCCESS; } } void CreateHash(HashTable &H) /*创建哈希表*/ { int s; int e; cout << "请输入哈希表:(输入0结束!)" << endl; cin >> e; while (e) { s = InsertHash(H, e); if (!s) { cout << "此数已存在!"; cin >> e; } else cin >> e; } } void PrintHash(HashTable H) /*显示元素及其位置*/ { cout << "哈希表地址:"; int i; for (i = 0; i < MAXSIZE; i++) cout << i << " "; cout << endl<< "关键字: "; for (i = 0; i < MAXSIZE; i++) cout << H.elem[i] << " "; cout << endl<< "关键字标志:"; for (i = 0; i < MAXSIZE; i++) cout << H.elemflag[i] << " "; } int DeleteHash(HashTable &H, int e) /*删除元素e*/ { int i; int a = 0; for (i = 0; i < MAXSIZE; i++) if (H.elem[i] == e && H.elemflag[i] == 1) { H.elemflag[i] = 2; H.count--; H.elem[i] = 0; a++; return SUCCESS; } if (!a) { cout << "无此数!" << endl; return 0; //return UNSUCCESS; } return 0; } void main() { HashTable H; int m, k, p; int R; do { cout << endl << "\t\t******************请选择功能********************" << endl; cout << "\t\t\t1.初始化哈希表" << endl << "\t\t\t2.创建哈希表" << endl << "\t\t\t3.查找" << endl << "\t\t\t4.插入" << endl << "\t\t\t5.删除" << endl << "\t\t\t6.输出哈希表:" << endl << "\t\t\t0.退出" << endl; cout << "\t\t************************************************" << endl; cin >> m; switch (m) { case 1: InitialHash(H); break; case 2: CreateHash(H); break; case 3: cout << endl << "请输入要查找的关键字:"; cin >> k; p = SearchHash(H, k); if (p) cout << "查找成功!" << endl; else cout << "查找失败!" << endl; break; case 4: cout << endl << "请输入要插入的关键字:"; cin >> R; p = InsertHash(H, R); if (p) cout << "插入成功!" << endl; else cout << "插入失败!" << endl; break; case 5: cout << "请输出要删除的关键字:"; cin >> R; p = DeleteHash(H, R); if (p) cout << "删除成功!" << endl; else cout << "删除失败!" << endl; break; case 6: PrintHash(H); break; case 0: break; default: cout << endl << "选择错误!"; break; } } while (m != 0); }