1. 程式人生 > >常用hash演算法對比

常用hash演算法對比

我來做一個比喻吧。 
我們有很多的小豬,每個的體重都不一樣,假設體重分佈比較平均(我們考慮到公斤級別),我們按照體重來分,劃分成100個小豬圈。 
然後把每個小豬,按照體重趕進各自的豬圈裡,記錄檔案。

好了,如果我們要找某個小豬怎麼辦呢?我們需要每個豬圈,每個小豬的比對嗎? 
當然不需要了。

我們先看看要找的這個小豬的體重,然後就找到了對應的豬圈了。 
在這個豬圈裡的小豬的數量就相對很少了。 
我們在這個豬圈裡就可以相對快的找到我們要找到的那個小豬了。

對應於hash演算法。 
就是按照hashcode分配不同的豬圈,將hashcode相同的豬放到一個豬圈裡。 
查詢的時候,先找到hashcode對應的豬圈,然後在逐個比較裡面的小豬。

所以問題的關鍵就是建造多少個豬圈比較合適。

如果每個小豬的體重全部不同(考慮到毫克級別),每個都建一個豬圈,那麼我們可以最快速度的找到這頭豬。缺點就是,建造那麼多豬圈的費用有點太高了。

如果我們按照10公斤級別進行劃分,那麼建造的豬圈只有幾個吧,那麼每個圈裡的小豬就很多了。我們雖然可以很快的找到豬圈,但從這個豬圈裡逐個確定那頭小豬也是很累的。

所以,好的hashcode,可以根據實際情況,根據具體的需求,在時間成本(更多的豬圈,更快的速度)和空間本(更少的豬圈,更低的空間需求)之間平衡。

Hash演算法有很多很多種類。具體的可以參考之前我寫的Hash演算法的一些分析。本處給大家提供一個集合了很多使用的Hash演算法的類,應該可以滿足不少人的需要的:

Java程式碼 

常用的字串Hash函式還有ELFHash,APHash等等,都是十分簡單有效的方法。這些函式使用位運算使得每一個字元都對最後的函式值產生影響。另外還有以MD5和SHA1為代表的雜湊函式,這些函式幾乎不可能找到碰撞。

常用字串雜湊函式有BKDRHash,APHash,DJBHash,JSHash,RSHash,SDBMHash,PJWHash,ELFHash等等。對於以上幾種雜湊函式,我對其進行了一個小小的評測。

Hash函式 資料1 資料2 資料3 資料4 資料1得分 資料2得分 資料3得分 資料4得分 平均分
BKDRHash 2 0 4774 481 96.55 100 90.95 82.05 92.64
APHash 2 3 4754 493 96.55 88.46 100 51.28 86.28
DJBHash 2 2 4975 474 96.55 92.31 0 100 83.43
JSHash 1 4 4761 506 100 84.62 96.83 17.95 81.94
RSHash 1 0 4861 505 100 100 51.58 20.51 75.96
SDBMHash 3 2 4849 504 93.1 92.31 57.01 23.08 72.41
PJWHash 30 26 4878 513 0 0 43.89 0 21.95
ELFHash 30 26 4878 513 0 0 43.89 0 21.95

其中資料1為100000個字母和數字組成的隨機串雜湊衝突個數。資料2為100000個有意義的英文句子雜湊衝突個數。資料3為資料1的雜湊值與1000003(大素數)求模後儲存到線性表中衝突的個數。資料4為資料1的雜湊值與10000019(更大素數)求模後儲存到線性表中衝突的個數。

經過比較,得出以上平均得分。平均數為平方平均數。可以發現,BKDRHash無論是在實際效果還是編碼實現中,效果都是最突出的。APHash也是較為優秀的演算法。DJBHash,JSHash,RSHash與SDBMHash各有千秋。PJWHash與ELFHash效果最差,但得分相似,其演算法本質是相似的。

在資訊修競賽中,要本著易於編碼除錯的原則,個人認為BKDRHash是最適合記憶和使用的