1. 程式人生 > >雜湊函式(雜湊函式,Hash Function)

雜湊函式(雜湊函式,Hash Function)

說明

         雜湊的概念屬於查詢,它不以關鍵字的比較為基本操作,採用直接定址技術。在理想情況下,查詢的期望時間為O(1)。

簡單的說,hash函式就是把任意長的輸入字串變化成固定長的輸出字串的一種函式。輸出字串的長度稱為hash函式的位數。(下圖來源於維基百科)

雜湊函式把訊息或資料壓縮成摘要,使得資料量變小,將資料的格式固定下來,比如我們自定義密碼的儲存。


一句話:雜湊(Hashing)通過雜湊函式將要檢索的項與索引(雜湊,雜湊值)關聯起來,生成一種便於搜尋的資料結構(散列表)。

應用

目前應用最為廣泛的hash函式是SHA-1和MD5,大多是128位和更長。hash函式在現實生活中應用十分廣泛。很多下載網站都提供下載檔案的MD5碼校驗,可以用來判別檔案是否完整,在一些BitTorrent下載中,軟體將通過計算MD5檢驗下載到的檔案片段的完整性,etc.


解釋

雜湊函式的性質:

同一函式的雜湊值不相同,那麼其原始輸入也不相同,上圖中k1,k3和k4。(確定性)

雜湊函式的輸入和輸出不是唯一對應關係的,如果兩個雜湊值相同,兩個輸入值很可能是不相同的,上圖中的k2,k5這種情況稱為“雜湊碰撞”。(不確定性)

 

所以,安全避免衝突的條件,一是|U|的上限為m,(實際上很難滿足);二是選擇合適的Hash函式。

 

Q:衝突是不是可以避免的?

否。根據鴿巢原理可得,雜湊表的重複問題(衝突)是不可避免的,因為鍵的數目總是比索引的數目多,不管是多麼高明的演算法都不可能解決這個問題。就算鍵的數目比索引的數目少,必有一個輸出串對應多個輸入串,衝突還是會發生。

 

hash函式的構造準則:簡單、均勻

1、  雜湊函式的計算簡單,快速;

2、  雜湊函式能將關鍵字集合K均勻地分佈在地址集{0,1,…,m-1}上,使衝突最小。

 

hash函式的構造方法:

1、直接定址法:

         取關鍵字或關鍵字的某個線性函式值為雜湊地址:H(key)=key 或 H(key)=a·key+b

其中a和b為常數,這種雜湊函式叫做自身函式。

例:有一個從1歲到100歲的人口數字統計表,其中,年齡作為關鍵字,雜湊函式取關鍵字自身。這樣,若要詢問25歲的人有多少,則只要查表的第25項即可。

         由於直接定址所得地址集合和關鍵字集合的大小相同。因此,對於不同的關鍵字不會發生衝突。但實際中能使用這種雜湊函式的情況很少。

2、  相乘取整法

該方法包括兩個步驟:首先用關鍵字key乘上某個常數A(0<A<1),並抽取出key.A的小數部分;然後用m乘以該小數後取整。即:
         

該方法最大的優點是m的選取比除餘法要求更低。比如,完全可選擇它是2的整數次冪。雖然該方法對任何A的值都適用,但對某些值效果會更好。Knuth建議選取
             

3、平方取中法

         取關鍵字平方後的中間幾位為雜湊地址。

通過平方擴大差別,另外中間幾位與乘數的每一位相關,由此產生的雜湊地址較為均勻。這是一種較常用的構造雜湊函式的方法。

例:將一組關鍵字(0100,0110,1010,1001,0111)

平方後得(0010000,0012100,1020100,1002001,0012321)

若取表長為1000,則可取中間的三位數作為雜湊地址集:(100,121,201,020,123)。

4、摺疊法

將關鍵字分割成位數相同的幾部分(最後一部分的位數可以不同),然後取這幾部分的疊加和(捨去進位)作為雜湊地址,這方法稱為摺疊法(folding)。

如國際標準圖書編號0-442-20586-4的雜湊地址分別如


5、除餘法:

取關鍵字被數p除後所得餘數為雜湊地址:H(key)=keyMOD p (p≤m)

這是一種最簡單,也最常用的構造雜湊函式的方法。它不僅可以對關鍵字直接取模(MOD),也可在折迭、平方取中等運算之後取模。值得注意的是,在使用除留餘數法時,對p的選擇很重要。一般情況下可以選p為質數或不包含小於20的質因素的合數。

6、隨機數法

   選擇一個隨機函式,取關鍵字的隨機函式值為它的雜湊地址,即H(key)=random (key),其中random為隨機函式。通常,當關鍵字長度不等時採用此法構造雜湊函式較恰當。

 

處理衝突的方法:

1、開放定址法(不好理解啊

基本思想:前者是將所有結點均存放在散列表[0..m-1]中。

當衝突發生時,使用某種探查(亦稱探測)技術在散列表中形成一個探查(測)序列。沿此序列逐個單元地查詢,直到找到給定的關鍵字,或者碰到一個開放的地址 (即該地址單元為空)為止(若要插入,在探查到開放的地址,則可將待插入的新結點存人該地址單元)。查詢時探查到開放的地址則表明表中無待查的關鍵字,即查詢失敗。

 

注意:用開放定址法建立散列表時,建表前須將表中所有單元(更嚴格地說,是指單元中儲存的關鍵字)置空。

怎麼用

裝填因子:a,a一般取0.5到0.9之間。目的是為了確定合適的表長。

探查序列:

Hi=(H(key)+di)MOD m        i=1,2,…,k (k≤m-1) ,其中:H(key)為雜湊函式;m為雜湊表表長;di為增量序列,可有下列三種取法:

(1)    di=1,2,3,…,m-1,稱線性探測再雜湊;

(2)    di=12,-12,22,-22,33,…,±k2,(k≤m/2)稱二次探測再雜湊;

(3)    di=偽隨機數序列,稱偽隨機探測再雜湊。

 

例:利用探測法構造散列表

已知一組關鍵字為(26,36,41,38,44,15,68,12,06,51),用除餘法構造雜湊函式,用線性探查法解決衝突構造這組關鍵字的散列表。

這裡關鍵字個數n=10,不妨取m=13,此時α≈0.77,散列表為T[0..12],雜湊函式為:h(key)=key%13。

由除餘法的雜湊函式計算出的上述關鍵字序列的雜湊地址為

(0,10,2,12,5,2,3,12,6,12)。

步驟

1、前5個關鍵字插入時,其相應的地址均為開放地址,故將它們直接插入T[0],T[10),T[2],T[12]和T[5]中。

2、當插入第6個關鍵字15時,其雜湊地址2(即h(15)=15%13=2)已被關鍵字41(15和41互為同義詞)佔用。故探查h1=(2+1)%13=3,此地址開放,所以將15放入T[3]中。當插入第7個關鍵字68時,其雜湊地址3已被非同義詞15先佔用,故將其插入到T[4]中。
3、當插入第8個關鍵字12時,雜湊地址12已被同義詞38佔用,故探查hl=(12+1)%13=0,而T[0]亦被26佔用,再探查h2=(12+2)%13=1,此地址開放,可將12插入其中。

4、類似地,第9個關鍵字06直接插入T[6]中;而最後一個關鍵字51插人時,因探查的地址12,0,1,…,6均非空,故51插入T[7]中。

參見動畫演示

 

2、鏈地址法

基本思想:將互為同義詞的結點鏈成一個單鏈表,而將此連結串列的頭指標放在散列表[0..m-1]中。

 

例:已知一組關鍵字為(19,14,23,01,68,20,84,27,55,11,10,79),則按雜湊函式H(key)=key MOD13和鏈地址法處理衝突構造所得的雜湊表為: