【學習總結】哈希表:哈希函數構造;哈希表解決地址衝突的方法

小結

  • 散列函數構造方法:

    • 1.直接定址法:H(key) = a*key + b
    • 2.除留餘數法:H(key) = key % p(p爲不大於散列表表長,但最接近或等於表長的質數p)
    • 3.數字分析法:選取r進制數數碼分佈較爲均勻的若干位做爲散列地址
    • 4.平方取中法:取關鍵字的平方值的中間幾位做爲散列地址
    • 5.摺疊法:將關鍵字分割成位數相同的幾部分,而後取這幾部份的疊加和做爲散列地址
  • 處理衝突的方法:

    • 1.開放定址法(閉哈希表):在衝突的哈希地址的基礎上進行處理,獲得新的地址值。Hi = (H(key)+di) % m(m表示散列表表長,di爲增量序列)
      • 1)線性探測法:dii=1,2,3,…,m-1
      • 2)二次探測法:di=12,-12,22,-22,…,k2,-k2 ( k<=m/2 )
        • 衝突發生時,以原哈希地址爲中心,在表的左右進行跳躍式探測,比較靈活。
      • 3)僞隨機數法:di=僞隨機數序列。
        • 具體實現時,應創建一個僞隨機數發生器,(如i=(i+p) % m),並給定一個隨機數作起點。
    • 線性探測再散列的優勢是:只要哈希表不滿,就必定能找到一個不衝突的哈希地址,而二次探測再散列和僞隨機探測再散列則不必定。
    • 注:在開放定址的情形下,不能隨便物理刪除表中已有元素,若刪除元素將會截斷其餘具備相同散列地址的元素的查找地址。若想刪除一個元素,給它作一個刪除標記,進行邏輯刪除。
    • 2.鏈地址法、拉鍊法(開哈希表)
      • 將全部哈希地址爲i的元素構成一個稱爲同義詞鏈的單鏈表,並將單鏈表的頭指針存在哈希表的第i個單元中,於是查找、插入和刪除主要在同義詞鏈中進行。鏈地址法適用於常常進行插入和刪除的狀況。
    • 3.再哈希法:同時構造多個不一樣的哈希函數,發生衝突時,使用其餘哈希函數求值。這種方法不易產生彙集,但增長了計算時間。
    • 4.創建公共溢出區:將哈希表分爲基本表和溢出表兩部分,凡是和基本表發生衝突的元素,一概填入溢出表

概述

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

  • 當關鍵字集合很大時,關鍵字值不一樣的元素可能會映象到哈希表的同一地址上,即 k1≠k2 ,但 H(k1)=H(k2),這種現象稱爲衝突,此時稱k1和k2爲同義詞。實際中,衝突是不可避免的,只能經過改進哈希函數的性能來減小衝突。dom

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

1)如何構造哈希函數性能

2)如何處理衝突。測試

哈希函數的構造方法

  • 構造哈希函數的原則是:①函數自己便於計算;②計算出來的地址分佈均勻,即對任一關鍵字k,f(k) 對應不一樣地址的機率相等,目的是儘量減小衝突。編碼

  • 下面介紹構造哈希函數經常使用的五種方法。指針

1. 數字分析法

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

2. 平方取中法

  • 當沒法肯定關鍵字中哪幾位分佈較均勻時,能夠先求出關鍵字的平方值,而後按須要取平方值的中間幾位做爲哈希地址。這是由於:平方後中間幾位和關鍵字中每一位都相關,故不一樣關鍵字會以較高的機率產生不一樣的哈希地址。code

  • 例:咱們把英文字母在字母表中的位置序號做爲該英文字母的內部編碼。例如K的內部編碼爲11,E的內部編碼爲05,Y的內部編碼爲25,A的內部編碼爲01, B的內部編碼爲02。由此組成關鍵字「KEYA」的內部代碼爲11052501,同理咱們能夠獲得關鍵字「KYAB」、「AKEY」、「BKEY」的內部編碼。以後對關鍵字進行平方運算後,取出第7到第9位做爲該關鍵字哈希地址,如圖。
    blog

3. 分段疊加法

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

4. 除留餘數法

  • 假設哈希表長爲m,p爲小於等於m的最大素數,則哈希函數爲基礎

  • h(k)=k % p ,其中%爲模p取餘運算。

  • 例如,已知待散列元素爲(18,75,60,43,54,90,46),表長m=10,p=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

  • 此時沒有衝突,如圖。

5. 僞隨機數法

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

  • 在實際應用中,應根據具體狀況,靈活採用不一樣的方法,並用實際數據測試它的性能,以便作出正確斷定。一般應考慮如下五個因素 :

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

l 關鍵字的長度。

l 哈希表大小。

l 關鍵字分佈狀況。

l 記錄查找頻率

處理衝突的方法

  • 經過構造性能良好的哈希函數,能夠減小衝突,但通常不可能徹底避免衝突,所以解決衝突是哈希法的另外一個關鍵問題。建立哈希表和查找哈希表都會遇到衝突,兩種狀況下解決衝突的方法應該一致。下面以建立哈希表爲例,說明解決衝突的方法。經常使用的解決衝突方法有如下四種:

1. 開放定址法

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

    Hi=(H(key)+di)% m   i=1,2,…,n
  • 其中H(key)爲哈希函數,m 爲表長,di稱爲增量序列。增量序列的取值方式不一樣,相應的再散列方式也不一樣。主要有如下三種:

l 線性探測再散列

dii=1,2,3,…,m-1

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

l 二次探測再散列

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

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

l 僞隨機探測再散列

di=僞隨機數序列。

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

例如,已知哈希表長度m=11,哈希函數爲:H(key)= key % 11,則H(47)=3,H(26)=4,H(60)=5,假設下一個關鍵字爲69,則H(69)=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)。若是用僞隨機探測再散列處理衝突,且僞隨機數序列爲:2,5,9,……..,則下一個哈希地址爲H1=(3 + 2)% 11 = 5,仍然衝突,再找下一個哈希地址爲H2=(3 + 5)% 11 = 8,此時再也不衝突,將69填入8號單元,參圖8.26 (c)。

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

2. 再哈希法

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

    Hi=RH1(key) i=1,2,…,k

  • 當哈希地址Hi=RH1(key)發生衝突時,再計算Hi=RH2(key)……,直到衝突再也不產生。這種方法不易產生彙集,但增長了計算時間。

3. 鏈地址法

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

  • 例如,已知一組關鍵字(32,40,36,53,16,46,71,27,42,24,49,64),哈希表長度爲13,哈希函數爲:H(key)= key % 13,則用鏈地址法處理衝突的結果如圖8.27所示:

  • 本例的平均查找長度 ASL=(17+24+3*1)=1.5

四、創建公共溢出區

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

END

相關文章
相關標籤/搜索