1. 程式人生 > >雜湊儲存、雜湊表原理

雜湊儲存、雜湊表原理

雜湊表的定義

雜湊儲存的基本思想是以關鍵字Key為自變數,通過一定的函式關係(雜湊函式或雜湊函式),計算出對應的函式值(雜湊地址),以這個值作為資料元素的地址,並將資料元素存入到相應地址的儲存單元中。

查詢時再根據要查詢的關鍵字採用同樣的函式計算出雜湊地址,然後直接到相應的儲存單元中去取要找的資料元素即可。

雜湊表的應用

雜湊表(hash table)是實現字典操作的一種有效的資料結構。

儘管最壞的情況下,散列表中查詢一個元素的時間與連結串列中查詢的時間相同,達到了O(n)。然而實際應用中,雜湊的查詢的效能是極好的。在一些合理的假設下,在散列表中查詢一個元素的平均時間是O(1)。

建立雜湊表操作步驟

1) step1 取資料元素的關鍵字key,計算其雜湊函式值(地址)。若該地址對應的儲存空間還沒有被佔用,則將該元素存入;否則執行step2解決衝突。

2) step2 根據選擇的衝突處理方法,計算關鍵字key的下一個儲存地址。若下一個儲存地址仍被佔用,則繼續執行step2,直到找到能用的儲存地址為止。

常用的雜湊函式

構造雜湊函式的方法有很多,總的原則是儘可能將關鍵字集合空間均勻的對映到地址集合空間中,同時儘可能降低衝突發生的概率。

1、除留餘數法:
H(Key) = key % p  (p ≤ m)

取關鍵字除以p的餘數作為雜湊地址,p最好選擇一個小於或等於m(雜湊地址集合的個數)的某個最大素數

雜湊表長度8163264128256512
最大素數7133161127251503
2、直接地址法
H(Key) = a * Key + b;這個“a,b”是常量。
3、數字分析法

比如有一組key1=112233,key2=112633,key3=119033,

針對這樣的數我們分析數中間兩個數比較波動,其他數不變。那麼我們取key的值就可以是 key1=22,key2=26,key3=90。

4、平方取中法

此處忽略,見名識意。

5、摺疊法

比如key=135790,要求key是2位數的雜湊值。那麼我們將key變為13+57+90=160,然後去掉高位“1”,此時key=60,

以上五種雜湊關係的目的就是地址與每一位的key都相關,來做到“雜湊地址”儘可能分散。

衝突處理方法

我們知道影響雜湊查詢效率的一個重要因素是雜湊函式本身。當兩個不同的資料元素的雜湊值相同時,就會發生衝突。為減少發生衝突的可能性,雜湊函式應該將資料儘可能分散地對映到雜湊表的每一個表項中。

解決衝突的方法有以下兩種:

(1) 開放地址法

如果兩個資料元素的雜湊值相同,則在雜湊表中為後插入的資料元素另外選擇一個表項。

當程式查詢雜湊表時,如果沒有在第一個對應的雜湊表項中找到符合查詢要求的資料元素,程式就會繼續往後查詢,直到找到一個符合查詢要求的資料元素,或者遇到一個空的表項。

①.線性探測法

這種方法在解決衝突時,依次探測下一個地址,直到有空的地址後插入,若整個空間都找遍仍然找不到空餘的地址,產生溢位。

Hi =( H(Key) + di ) % m  ( i = 1,2,3,...,k , k ≤ m-1 )

地址增量 di = 1,2,...,m-1 , 其中 i 為探測次數

②.二次探測法

地址增量序列為:di = 1^2,-1^2,2^2,-2^2 ,...,q^2,-q^2  (q ≤ m/2)

③.雙雜湊函式探測法

Hi =( H(Key) + i * RH(Key) ) % m      ( i = 1,2,3,..., m-1 )

H(Key) , RH(Key) 是兩個雜湊函式,m為雜湊表長度。

先用第一個雜湊函式對關鍵字計算雜湊地址,一旦產生地址衝突,再用第二個函式確定移動的步長因子,最後通過步長因子序列由探測函式尋找空餘的雜湊地址。

H1 = ( a+b )%m , H2 = ( a + 2b )%m , ... , Hm-1 = ( a+(m-1)*b )%m
(2) 鏈地址法

將雜湊值相同的資料元素存放在一個連結串列中,在查詢雜湊表的過程中,當查詢到這個連結串列時,必須採用線性查詢方法。


Python字典dict的實現是使用開放定址法中的二次探查來解決衝突的。