1. 程式人生 > >構造雜湊表以及二次探測法

構造雜湊表以及二次探測法

構造雜湊表(散列表)以及二次探測法

今天做筆試題時,遇到一道構造雜湊表的題,hash函式是 k%11 ,然後一個數組記不清了,然後就是問二次探測法進行,問下面那個是正確,懵逼啊,沒做過,不知道,亂選直接下一題,於是有這個部落格,趕緊學習一波。

網上查詢了一下。

構造雜湊表的幾種方法

常用方法是直接定址法除留餘數法

  • 直接定址法(取關鍵字的某個線性函式為雜湊地址)

類似於這樣的式子

f(key) = a × key + b

  • 除留餘數法(取關鍵值被某個不大於散列表長m的數p除後的所得的餘數為雜湊地址)

對於散列表長為m的雜湊函式公式為:

f( key ) = key mod p ( p ≤ m )

mod是取模(求餘數)的意思。事實上,這方法不僅可以對關鍵字直接取模,也可在摺疊、平方取中後再取模。

  • 平方取中法

  • 摺疊法

  • 隨機數法

  • 數學分析法

雜湊衝突(碰撞)以及處理

雜湊衝突:既然有雜湊函式Hash(key),在有限的空間裡,肯定會產生相同的的值(雜湊地址),我們稱這種情況為雜湊衝突(碰撞)。任意的雜湊函式都不能避免產生衝突。

1. 開發定址法

所謂的開放定址法就是一旦發生了衝突,就去尋找下一個空的雜湊地址,只要散列表足夠大,空的雜湊地址總能找到,並將記錄存入。

  • 線性探測法

fi(key) = (f(key)+di) MOD m (di=1,2,3,......,m-1)

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

ep:我們的關鍵字集合為{12,67,56,16,25,37,22,29,15,47,48,34},表長為12。 我們用雜湊函式f(key) = key mod 12。

當計算前S個數{12,67,56,16,25}時,都是沒有衝突的雜湊地址,直接存入:

這裡寫圖片描述

計算key = 37時,發現f(37) = 1,此時就與25所在的位置衝突。

於是我們應用上面的公式f(37) = (f(37)+1) mod 12 = 2。於是將37存入為2的下標位置。

這裡寫圖片描述

接下來22,29,15,47都沒有衝突,正常的存入:

這裡寫圖片描述

到了 key=48,我們計算得到f(48) = 0,與12所在的0位置衝突了,不要緊,我們f(48) = (f(48)+1) mod 12 = 1,此時又與25所在的位置衝突。於是f(48) = (f(48)+2) mod 12=2,還是衝突……一直到 f(48) = (f(48)+6) mod 12 = 6時,存入該位置:

這裡寫圖片描述

我們把這種解決衝突的開放定址法稱為線性探測法。

  • 二次探測法

考慮深一步,如果發生這樣的情況,當最後一個key=34,f(key)=10,與22所在的位置衝突,可是22後面沒有空位置了,反而它的前面有一個空位置,儘管可以 不斷地求餘數後得到結果,但效率很差。

因此我們可以改進di = 12, -12, 22, -22,……, q2, -q2 (q <= m/2),這樣就等於是可以雙向尋找到可能的空位置。

對於34來說,我 們取di即可找到空位置了。另外增加平方運算的目的是為了不讓關鍵字都聚集在 某一塊區域。我們稱這種方法為二次探測法。

f(key) = (f(key)+di) MOD m (di = 1^2, -1^2, 2^2, -2^2,……, q^2, -q^2, q <= m/2)

注:1^2 表示是 1的平方。

2. 鏈地址法

前面我們談到了雜湊衝突處理的開放定址法,它的思路就是一旦發生了衝突,就去尋找下一個空的雜湊地址。那麼,有衝突就非要換地方呢,我們直接就在原地處理行不行呢?

答案是可以的,就是鏈地址法,就好比Java裡的HashMap的資料結構一樣。

這裡寫圖片描述