散列表(Hash表)
1、散列查找的基本思想
散列技术是在记录的存储位置和它的关键字之间的一个确定的对应关系f,使得每一个关键字key对应的一个存储位置f(key)。这里我们把这种对应关系f称为散列表函数,又称为哈希函数。采用存储在一块连续的空间中,这块连续存储空间称为散列表或哈希表(Hash table)。
2、散列表的查找步骤
3、散列表函数的设计
3.1、直接定址法
直接定值法是关键码的线性函数:
直接定值法的特点是不会产生冲突,但实际使用这种散列函数的情况很少
3.2、保留余数法
保留余数法的思想是选择某个正整数p以关键码除以p的余数作为散列表地址即:
这个办法的关键在于选取合适的p,否则容易产生同义词。一般情况下,若散列表表长为m通常以选取p为小于或等于m的最大素数或不包括小于20质因子的合数。
3.3、平方取中法
平方取中法是对关键码平方后,按散列表大小,取中间的若干位作为散列表的地址,其原理是一个是平方后,中间的若干位作为散列表,其原理是一个数平方后,中间的几位分布较均匀,从而冲突发生的概率较为小,例如对于关键码1234,假设散列表地址是2,由于1234的平方等于1522756,选取的中间的2位作为散列地址,可以选22页可以选27.
4、处理冲突的方法
4.1、开放定值法
线性探测法处理冲突:
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| #include<iostream> using namespace std; #define NIL 0 #define DelNIL -1 #define m 13 #define n 20 typedef struct { int key; } LHashTable;
void HashListInit(LHashTable HT[n]) { int i; for (i = 0; i < n; i++) HT[i].key = NIL; }
void HashListClear(LHashTable HT[]) { int i; for (i = 0; i < n; i++) HT[i].key = NIL; }
int Hash(int k) { return (k % m); }
int HashListSearch(LHashTable HT[n], int k) { int d, temp; d = Hash(k); temp = d; while (HT[d].key != NIL) { if (HT[d].key == k) { return d; }
else { d = (d + 1) % m; }
if (d == temp) return -1; } return -1; }
void HashListInsert(LHashTable HT[n], int k) { int d, temp; d = Hash(k); temp = d; while (HT[d].key != NIL && HT[d].key != DelNIL) { d++; if (d == temp) { cout << "哈希表无空间" << endl; return; } } HT[d].key = k; }
void HashListDelete(LHashTable HT[n], int k) { int d, temp; d = Hash(k); temp = d; while (HT[d].key != NIL) { if (HT[d].key == k) { HT[d].key = DelNIL; return; } else { d = (d + 1) % m; } if (d == temp) break; } cout << "哈希表中无待删除元素" << k << endl; }
void PrintHashList(LHashTable HT[n]) { int i; for (i = 0; i < n; i++) cout << i << " "; cout << endl; for (i = 0; i < n; i++) cout << HT[i].key << " "; } int main() { int k; LHashTable HT[n]; HashListInit(HT); cout << "请输入要插入到哈希表中的关键字,以0结束:"; cin >> k; while (k != 0) { HashListInsert(HT, k); cin >> k; } cout << "所建立的哈希表长为20,哈希函数为H(key)=key%13" << endl; PrintHashList(HT); cout << "\n请输入要查找的关键字:"; cin >> k; k = HashListSearch(HT, k); if (k == -1) cout << "哈希表中无此元素" << endl; else cout << "查找的关键字位置为:" << k << endl; cout << "请输入要删除的关键字:"; cin >> k; HashListDelete(HT, k); cout << "删除成功后的哈希表为"; PrintHashList(HT); }
|
二次探测法构造的闭散列表进行查找:
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
| #include <iostream> using namespace std; typedef int DataType; struct Node { DataType data; Node* next; }; const int MaxSize = 11; class HashTable2 { public: HashTable2(); ~HashTable2(); int Insert(int k); bool Delete(int k); Node* Search(int k); void Print(); private: int hashCode(int k); Node* hashTable[MaxSize]; }; HashTable2::HashTable2() { for (int i = 0; i < MaxSize; i++) { hashTable[i] = NULL; } } HashTable2::~HashTable2() { Node* p = NULL, * q = NULL; for (int i = 0; i < MaxSize; i++) { p = q = hashTable[i]; while (p != NULL) { p = p->next; delete q; q = p; } } } int HashTable2::hashCode(int k) { return k % 11; } void HashTable2::Print() { Node* p = NULL; for (int i = 0; i < MaxSize; i++) { p = hashTable[i]; cout << i << " "; while (p != NULL) { cout << p->data << " "; p = p->next; } cout << endl; }
} Node* HashTable2::Search(int k) { int j = hashCode(k); Node* p = hashTable[j]; while (p != NULL) { if (p->data == k) { return p; } p = p->next; } return NULL; } int HashTable2::Insert(int k) { int j = hashCode(k); Node* p = Search(k); if (p != NULL) { return -1; } else { p = new Node; p->data = k; p->next = hashTable[j]; hashTable[j] = p; return 1; } } bool HashTable2::Delete(int k) { int j = hashCode(k); Node* p = hashTable[j]; Node* last = p; if (p->data == k) { hashTable[j] = p->next; return true; } else { p = p->next; } return false; } int main() { HashTable2 HT; int k = 0; cin >> k; while (k) { HT.Insert(k); cin >> k; } HT.Print(); cin >> k; bool sign = HT.Delete(k); if (sign) HT.Print(); else cout << "未找到此元素" << endl; return 0; }
|