Hash冲突处理终极版
對于Hash,我們是怎樣來處理沖突的。現在就來介紹一些經典的Hash沖突處理的方法。主要包括
?
? (1)開放地址法
? (2)拉鏈法
? (3)再哈希法
? (4)建立公共溢出區
?
(1)開放地址法
?
??? 基本思想:當發生地址沖突時,按照某種方法繼續探測Hash表中其它存儲單元,直到找到空位置為止。描述如下
?
????
?
??? 其中,為關鍵字的直接Hash地址,為Hash表的長度,為
??? 每次再探測時的地址增量。根據的不同取法,有不同的稱呼。
?
??? 線性探測再散列????
??? 二次探測再散列????
??? 偽隨機再散列????? ?偽隨機數
?
(2)拉鏈法
???
??? 拉鏈法又叫鏈地址法,適合處理沖突比較嚴重的情況。基本思想是把所有關鍵字為同義詞的記錄存儲在同一個
????線性鏈表中。
?
代碼:
#include <iostream> #include <string.h> #include <stdio.h>using namespace std; const int N = 35;struct node {int key; //關鍵字int len; //每個節點引出的鏈表長度bool flag; //有數據的標志node *next; };node list[N];void Init(node list[]) {for(int i=0; i<N; i++){list[i].len = 0;list[i].flag = 0;list[i].next = NULL;} }void Insert(node list[], int val, int m) {int id = val % m;if(!list[id].flag){list[id].key = val;list[id].flag = 1;}else{node *p = new node();p->key = val;p->next = list[id].next;list[id].next = p;} }//輸出HashTable void Print(node list[], int m) {for(int i=0; i<m; i++){node *p = list[i].next;if(!list[i].flag)printf("The %dth record is NULL!\n", i);else{printf("The %dth record is %d", i, list[i].key);list[i].len++;while(p){printf("->%d", p->key);p = p->next;list[i].len++;}puts("");}} }//計算平均查找長度 double ASL(node list[], int m) {double ans = 0;for(int i=0; i<m; i++)ans += (list[i].len + 1) * list[i].len / 2.0;return ans / m; }int main() {int n, m;Init(list);scanf("%d %d", &n, &m);for(int i=0; i<n; i++){int val;scanf("%d", &val);Insert(list, val, m);}Print(list, m);printf("The Average Search Length is %.5lf\n", ASL(list, m));return 0; }/** 12 11 47 7 29 11 16 92 22 8 3 37 89 50 */
關于拉鏈法還可以參考:http://www.51nod.com/question/index.html#!questionId=1191
?
(3)再哈希法
?
??? 再哈希法又叫雙哈希法,有多個不同的Hash函數,當發生沖突時,使用第二個,第三個,....,等哈希函數
??? 計算地址,直到無沖突。雖然不易發生聚集,但是增加了計算時間。
?
(4)建立公共溢出區
?
??? 建立公共溢出區的基本思想是:假設哈希函數的值域是[1,m-1],則設向量HashTable[0...m-1]為基本
??? 表,每個分量存放一個記錄,另外設向量OverTable[0...v]為溢出表,所有關鍵字和基本表中關鍵字為同義
??? 詞的記錄,不管它們由哈希函數得到的哈希地址是什么,一旦發生沖突,都填入溢出表。
?
?
???
總結
以上是生活随笔為你收集整理的Hash冲突处理终极版的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 伯努利数与自然数幂和
- 下一篇: 多项式乘法运算初级版