好的散列函數的特點:
每個關鍵字都等可能的散列到m個槽位中的任何一個之中去,並且與其他的關鍵字已經被散列到哪個槽位中去無關。但是一般都不太可能檢查這個條件是否成立,因爲很少知道關鍵字所符合的概率分佈。
將關鍵字解釋爲自然數:
一般都有方法可以將關鍵字不是自然數的轉化爲自然數,如對於字符串,pt,可以被解釋爲十進制整數對(112,116),這是因爲在ASCII中p=112,t=116,然後按照128爲基數來表示,故pt可以表示爲112*128+116=14,452。這樣就把一個字符串轉化爲了一個整數,雖然這個整數很大。
典型的散列函數:
1、除法散列法
散列函數爲:
h(k) = k mod m;
m爲散列表的大小。可以選取m的值爲與2的整數次冪不太接近的質數。例如散列表中要存放n=2000個字符串,每個字符有8位,一次不成功的查找大約要檢查3個元素,因此分配的散列表的大小爲m=701.因爲此時它接近2000/3、但是有不接近2的任何冪次的質數,然後把每個關鍵字都是爲整數,則我們有散列函數:h(k) = k mod 701;
2、乘法散列法
散列函數爲:
h(k) =⌊m(kA-⌊kA⌋)⌋。
m爲散列表的大小。對於m、k、A的要求,一般是取m爲2的摸個冪次,然後0<A<1,一般取爲(√5-1)/2,即0.6180339887.....
3、全域散列法
全域散列的基本思想是再執行開始的時候就從一組仔細設計的函數中,隨即的選擇一個作爲散列函數。這樣就可以使散列函數獨立於要存儲的關鍵字,保證了沒有哪一種輸入會是中國導致最壞的情況性態。同時,隨機化也使得即使沒事對同一個輸入,算大也在每次執行時的性態也是不一樣的,使得算法具有較好的平均情況性態。
怎樣設計一個全域散列函數類?
選擇一個足夠大的質數p,使得每個可能的額關鍵字k都落在o到p-1的範圍之內(包括0和p-1)。設Zp表示集合{0,1,2,3,.......p-1},Zp*表示{1,2,3,........p-1},然後對於任意的a屬於Zp*,b屬於Zp,定義散列函數ha,b=((ak+b) mod p) mod m。所有的這樣的散列函數就構成了一個散列函數簇Hp,m={ha,b:a屬於Zp*,b屬於Zp}。由已知,Hp,m中有p(p-1)個散列函數。
上述講述的是通過鏈接法來解決碰撞問題,下邊講述通過開放尋址法來解決碰撞。
1、線性探查
2、二次探查
3、雙重散列
使用完全散列技術