1. 程式人生 > >雜湊衝突的解決方法

雜湊衝突的解決方法

1.基本概念

雜湊演算法:根據設定的雜湊函式H(key)和處理衝突方法將一組關鍵字映象到一個有限的地址區間上的演算法。也稱為雜湊演算法、雜湊演算法。
雜湊表:資料經過雜湊演算法之後得到的集合。這樣關鍵字和資料在集合中的位置存在一定的關係,可以根據這種關係快速查詢。
非雜湊表:與雜湊表相對應,集合中的 資料和其存放位置沒任何關聯關係的集合。

由此可見,雜湊演算法是一種特殊的演算法,能將任意資料雜湊後對映到有限的空間上,通常計算機軟體中用作快速查詢或加密使用。

雜湊衝突:由於雜湊演算法被計算的資料是無限的,而計算後的結果範圍有限,因此總會存在不同的資料經過計算後得到的值相同,這就是雜湊衝突。

2.解決雜湊衝突的方法

解決雜湊衝突的方法一般有:開放定址法、鏈地址法(拉鍊法)、再雜湊法、建立公共溢位區等方法。

2.1 開放定址法

從發生衝突的那個單元起,按照一定的次序,從雜湊表中找到一個空閒的單元。然後把發生衝突的元素存入到該單元的一種方法。開放定址法需要的表長度要大於等於所需要存放的元素。
在開放定址法中解決衝突的方法有:線行探查法、平方探查法、雙雜湊函式探查法。
開放定址法的缺點在於刪除元素的時候不能真的刪除,否則會引起查詢錯誤,只能做一個特殊標記。只到有下個元素插入才能真正刪除該元素。

2.1.1 線行探查法

線行探查法是開放定址法中最簡單的衝突處理方法,它從發生衝突的單元起,依次判斷下一個單元是否為空,當達到最後一個單元時,再從表首依次判斷。直到碰到空閒的單元或者探查完全部單元為止。
可以參考csdn上flash對該方法的演示:

http://student.zjzk.cn/course_ware/data_structure/web/flash/cz/kfdzh.swf

2.1.2 平方探查法

平方探查法即是發生衝突時,用發生衝突的單元d[i], 加上 1²、 2²等。即d[i] + 1²,d[i] + 2², d[i] + 3²...直到找到空閒單元。
在實際操作中,平方探查法不能探查到全部剩餘的單元。不過在實際應用中,能探查到一半單元也就可以了。若探查到一半單元仍找不到一個空閒單元,表明此散列表太滿,應該重新建立。

2.1.3 雙雜湊函式探查法

這種方法使用兩個雜湊函式hl和h2。其中hl和前面的h一樣,以關鍵字為自變數,產生一個0至m—l之間的數作為雜湊地址;h2也以關鍵字為自變數,產生一個l至m—1之間的、並和m互素的數(即m不能被該數整除)作為探查序列的地址增量(即步長),探查序列的步長值是固定值l;對於平方探查法,探查序列的步長值是探查次數i的兩倍減l;對於雙雜湊函式探查法,其探查序列的步長值是同一關鍵字的另一雜湊函式的值。

2.2 鏈地址法(拉鍊法)

連結地址法的思路是將雜湊值相同的元素構成一個同義詞的單鏈表,並將單鏈表的頭指標存放在雜湊表的第i個單元中,查詢、插入和刪除主要在同義詞連結串列中進行。連結串列法適用於經常進行插入和刪除的情況。
如下一組數字,(32、40、36、53、16、46、71、27、42、24、49、64)雜湊表長度為13,雜湊函式為H(key)=key%13,則連結串列法結果如下:

0       
1  -> 40 -> 27 -> 53 
2
3  -> 16 -> 42
4
5
6  -> 32 -> 71
7  -> 46
8
9
10 -> 36 -> 49
11 -> 24
12 -> 64

注:在java中,連結地址法也是HashMap解決雜湊衝突的方法之一,jdk1.7完全採用單鏈表來儲存同義詞,jdk1.8則採用了一種混合模式,對於連結串列長度大於8的,會轉換為紅黑樹儲存。

2.3 再雜湊法

就是同時構造多個不同的雜湊函式:
Hi = RHi(key) i= 1,2,3 ... k;
當H1 = RH1(key) 發生衝突時,再用H2 = RH2(key) 進行計算,直到衝突不再產生,這種方法不易產生聚集,但是增加了計算時間。

2.4 建立公共溢位區

將雜湊表分為公共表和溢位表,當溢位發生時,將所有溢位資料統一放到溢位區。



作者:冬天裡的懶喵
連結:https://www.jianshu.com/p/4d3cb99d7580
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。