哈希衝突的解決方法

1.基本概念

哈希算法:根據設定的哈希函數H(key)和處理衝突方法將一組關鍵字映象到一個有限的地址區間上的算法。也稱爲散列算法、雜湊算法。
哈希表:數據通過哈希算法以後獲得的集合。這樣關鍵字和數據在集合中的位置存在必定的關係,能夠根據這種關係快速查詢。
非哈希表:與哈希表相對應,集合中的 數據和其存放位置沒任何關聯關係的集合。java

因而可知,哈希算法是一種特殊的算法,能將任意數據散列後映射到有限的空間上,一般計算機軟件中用做快速查找或加密使用。web

哈希衝突:因爲哈希算法被計算的數據是無限的,而計算後的結果範圍有限,所以總會存在不一樣的數據通過計算後獲得的值相同,這就是哈希衝突。算法

2.解決哈希衝突的方法

解決哈希衝突的方法通常有:開放定址法、鏈地址法(拉鍊法)、再哈希法、創建公共溢出區等方法。函數

2.1 開放定址法

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

2.1.1 線行探查法

線行探查法是開放定址法中最簡單的衝突處理方法,它從發生衝突的單元起,依次判斷下一個單元是否爲空,當達到最後一個單元時,再從表首依次判斷。直到碰到空閒的單元或者探查徹底部單元爲止。
能夠參考csdn上flash對該方法的演示:
http://student.zjzk.cn/course_ware/data_structure/web/flash/cz/kfdzh.swfspa

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;對於雙散列函數探查法,其探查序列的步長值是同一關鍵字的另外一散列函數的值。code

2.2 鏈地址法(拉鍊法)

連接地址法的思路是將哈希值相同的元素構成一個同義詞的單鏈表,並將單鏈表的頭指針存放在哈希表的第i個單元中,查找、插入和刪除主要在同義詞鏈表中進行。鏈表法適用於常常進行插入和刪除的狀況。
以下一組數字,(3二、40、3六、5三、1六、4六、7一、2七、4二、2四、4九、64)哈希表長度爲13,哈希函數爲H(key)=key%13,則鏈表法結果以下:get

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的,會轉換爲紅黑樹存儲。flash

2.3 再哈希法

就是同時構造多個不一樣的哈希函數:
Hi = RHi(key) i= 1,2,3 ... k;
當H1 = RH1(key) 發生衝突時,再用H2 = RH2(key) 進行計算,直到衝突再也不產生,這種方法不易產生彙集,可是增長了計算時間。

2.4 創建公共溢出區

將哈希表分爲公共表和溢出表,當溢出發生時,將全部溢出數據統一放到溢出區。

做者:冬天裏的懶喵 連接:https://www.jianshu.com/p/4d3cb99d7580 來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。

相關文章
相關標籤/搜索