要求:根據數據元素的關鍵字和哈希函數建立哈希表並初始化哈希表,用開放定址法處理沖突,按屏幕輸出的功能表選擇所需的功能實現用哈希表對數據元素的插入,顯示,查找,刪除。
初始化哈希表時把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); }
