hash表以及處理衝突的方法

哈希表及處理衝突的方法

哈希法又稱散列法、雜湊法以及關鍵字地址計算法等,相應的表稱爲哈希表。這種方法的基本思想是:首先在元素的關鍵字k和元素的存儲位置p之間建立一個對應關係f,使得p=f(k)f稱爲哈希函數。創建哈希表時,把關鍵字爲k的元素直接存入地址爲f(k)的單元;以後當查找關鍵字爲k的元素時,再利用哈希函數計算出該元素的存儲位置p=f(k),從而達到按關鍵字直接存取元素的目的。

   當關鍵字集合很大時,關鍵字值不同的元素可能會映象到哈希表的同一地址上,即 k1k2 ,但 Hk1=Hk2),這種現象稱爲衝突,此時稱k1k2同義詞。實際中,衝突是不可避免的,只能通過改進哈希函數的性能來減少衝突。

綜上所述,哈希法主要包括以下兩方面的內容:

 1)如何構造哈希函數

 2)如何處理衝突。

8.4.1   哈希函數的構造方法

    構造哈希函數的原則是:函數本身便於計算;計算出來的地址分佈均勻,即對任一關鍵字kf(k) 對應不同地址的概率相等,目的是儘可能減少衝突。

下面介紹構造哈希函數常用的五種方法。

1 數字分析法

      如果事先知道關鍵字集合,並且每個關鍵字的位數比哈希表的地址碼位數多時,可以從關鍵字中選出分佈較均勻的若干位,構成哈希地址。例如,有80個記錄,關鍵字爲8位十進制整數d1d2d3…d7d8,如哈希表長取100,則哈希表的地址空間爲:00~99。假設經過分析,各關鍵字中 d4d7的取值分佈較均勻,則哈希函數爲:h(key)=h(d1d2d3…d7d8)=d4d7。例如,h(81346532)=43h(81301367)=06。相反,假設經過分析,各關鍵字中 d1d8的取值分佈極不均勻, d都等於5d都等於2,此時,如果哈希函數爲:h(key)=h(d1d2d3…d7d8)=d1d8,則所有關鍵字的地址碼都是52,顯然不可取。

2 平方取中法

當無法確定關鍵字中哪幾位分佈較均勻時,可以先求出關鍵字的平方值,然後按需要取平方值的中間幾位作爲哈希地址。這是因爲:平方後中間幾位和關鍵字中每一位都相關,故不同關鍵字會以較高的概率產生不同的哈希地址。

例:我們把英文字母在字母表中的位置序號作爲該英文字母的內部編碼。例如K的內部編碼爲11E的內部編碼爲05Y的內部編碼爲25A的內部編碼爲01, B的內部編碼爲02。由此組成關鍵字“KEYA”的內部代碼爲11052501,同理我們可以得到關鍵字“KYAB”、“AKEY”、“BKEY”的內部編碼。之後對關鍵字進行平方運算後,取出第7到第9位作爲該關鍵字哈希地址,如圖8.23所示。

 

關鍵字

內部編碼

內部編碼的平方值

H(k)關鍵字的哈希地址

KEYA

11050201

122157778355001

778

KYAB

11250102

126564795010404

795

AKEY

01110525

001233265775625

265

BKEY

02110525

004454315775625

315

8.23平方取中法求得的哈希地址

3 分段疊加法

      這種方法是按哈希表地址位數將關鍵字分成位數相等的幾部分(最後一部分可以較短),然後將這幾部分相加,捨棄最高進位後的結果就是該關鍵字的哈希地址。具體方法有摺疊法移位法。移位法是將分割後的每部分低位對齊相加,摺疊法是從一端向另一端沿分割界來回摺疊(奇數段爲正序,偶數段爲倒序),然後將各段相加。例如:key=12360324711202065,哈希表長度爲1000,則應把關鍵字分成3位一段,在此捨去最低的兩位65,分別進行移位疊加和摺疊疊加,求得哈希地址爲105907,如圖8.24所示。

 

1   2   3                    1   2   3

6   0   3                    3   0   6

2   4   7                    2   4   7

1   1   2                    2   1   1

+   0   2   0               +  0   2   0

        ————————            —————————

        1   1   0   5                    9   0   7

 

a)移位疊加                    (b) 摺疊疊加

 

                      8.24 由疊加法求哈希地址

 

4 除留餘數法

假設哈希表長爲mp爲小於等於m的最大素數,則哈希函數爲

hk=k  %  p ,其中%爲模p取餘運算。

例如,已知待散列元素爲(18756043549046),表長m=10p=7,則有

    h(18)=18 % 7=4    h(75)=75 % 7=5    h(60)=60 % 7=4   

    h(43)=43 % 7=1    h(54)=54 % 7=5    h(90)=90 % 7=6   

    h(46)=46 % 7=4

此時衝突較多。爲減少衝突,可取較大的m值和p值,如m=p=13,結果如下:

    h(18)=18 % 13=5    h(75)=75 % 13=10    h(60)=60 % 13=8    

    h(43)=43 % 13=4    h(54)=54 % 13=2    h(90)=90 % 13=12   

    h(46)=46 % 13=7

此時沒有衝突,如圖8.25所示。

 

0      1      2     3     4     5      6     7     8     9     10     11    12

 



54


43

18


46

60


75


90

                      8.25  除留餘數法求哈希地址

 

5 僞隨機數法

    採用一個僞隨機函數做哈希函數,即h(key)=random(key)

在實際應用中,應根據具體情況,靈活採用不同的方法,並用實際數據測試它的性能,以便做出正確判定。通常應考慮以下五個因素 

l         計算哈希函數所需時間 (簡單)。

l         關鍵字的長度。

l         哈希表大小。

l         關鍵字分佈情況。

l         記錄查找頻率

8.4.2   處理衝突的方法

   通過構造性能良好的哈希函數,可以減少衝突,但一般不可能完全避免衝突,因此解決衝突是哈希法的另一個關鍵問題。創建哈希表和查找哈希表都會遇到衝突,兩種情況下解決衝突的方法應該一致。下面以創建哈希表爲例,說明解決衝突的方法。常用的解決衝突方法有以下四種:

1.     開放定址法

這種方法也稱再散列法其基本思想是:當關鍵字key的哈希地址p=Hkey)出現衝突時,以p爲基礎,產生另一個哈希地址p1,如果p1仍然衝突,再以p爲基礎,產生另一個哈希地址p2,直到找出一個不衝突的哈希地址pi 將相應元素存入其中。這種方法有一個通用的再散列函數形式:

          Hi=Hkey+di% m   i=12…,n

    其中Hkey)爲哈希函數,爲表長,di稱爲增量序列。增量序列的取值方式不同,相應的再散列方式也不同。主要有以下三種:

l         線性探測再散列

    dii=123m-1

這種方法的特點是:衝突發生時,順序查看錶中下一單元,直到找出一個空單元或查遍全表。

l         二次探測再散列

    di=12-1222-22k2-k2    ( k<=m/2 )

    這種方法的特點是:衝突發生時,在表的左右進行跳躍式探測,比較靈活。

l         僞隨機探測再散列

    di=僞隨機數序列。

具體實現時,應建立一個僞隨機數發生器,(如i=(i+p) % m),並給定一個隨機數做起點。

例如,已知哈希表長度m=11,哈希函數爲:Hkey= key  %  11,則H47=3H26=4H60=5,假設下一個關鍵字爲69,則H69=3,與47衝突。如果用線性探測再散列處理衝突,下一個哈希地址爲H1=3 + 1% 11 = 4,仍然衝突,再找下一個哈希地址爲H2=3 + 2% 11 = 5,還是衝突,繼續找下一個哈希地址爲H3=3 + 3% 11 = 6,此時不再衝突,將69填入5號單元,參圖8.26 (a)。如果用二次探測再散列處理衝突,下一個哈希地址爲H1=3 + 12% 11 = 4,仍然衝突,再找下一個哈希地址爲H2=3 - 12% 11 = 2,此時不再衝突,將69填入2號單元,參圖8.26 (b)。如果用僞隨機探測再散列處理衝突,且僞隨機數序列爲:259……..,則下一個哈希地址爲H1=3 + 2% 11 = 5,仍然衝突,再找下一個哈希地址爲H2=3 + 5% 11 = 8,此時不再衝突,將69填入8號單元,參圖8.26 (c)

 

0        1       2      3      4      5       6      7      8       9      10    

 




47

26

60

69





         a 用線性探測再散列處理衝突

 

0        1       2      3      4      5       6      7      8       9      10    

 



69

47

26

60






         b 用二次探測再散列處理衝突

 

0        1       2      3      4      5       6      7      8       9      10    

 




47

26

60



69



         c 用僞隨機探測再散列處理衝突

 

                      8.26開放地址法處理衝突

從上述例子可以看出,線性探測再散列容易產生“二次聚集”,即在處理同義詞的衝突時又導致非同義詞的衝突。例如,當表中i, i+1 ,i+2三個單元已滿時,下一個哈希地址爲i, i+1 ,i+2,或i+3的元素,都將填入i+3這同一個單元,而這四個元素並非同義詞。線性探測再散列的優點是:只要哈希表不滿,就一定能找到一個不衝突的哈希地址,而二次探測再散列和僞隨機探測再散列則不一定。

2.       再哈希法

    這種方法是同時構造多個不同的哈希函數:

    Hi=RH1key  i=12k

當哈希地址Hi=RH1key)發生衝突時,再計算Hi=RH2key)……,直到衝突不再產生。這種方法不易產生聚集,但增加了計算時間。

3.        鏈地址法

    這種方法的基本思想是將所有哈希地址爲i的元素構成一個稱爲同義詞鏈的單鏈表,並將單鏈表的頭指針存在哈希表的第i個單元中,因而查找、插入和刪除主要在同義詞鏈中進行。鏈地址法適用於經常進行插入和刪除的情況。

例如,已知一組關鍵字(324036531646712742244964),哈希表長度爲13,哈希函數爲:Hkey= key % 13,則用鏈地址法處理衝突的結果如圖8.27所示:

 





wKiom1mk2HjDQzIcAAAGV5xTJdE380.png-wh_50

本例的平均查找長度 ASL=(1*7+2*4+3*1)=1.5

 

4建立公共溢出區

這種方法的基本思想是:將哈希表分爲基本表溢出表兩部分,凡是和基本表發生衝突的元素,一律填入溢出表


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章