1. 程式人生 > >雜湊表查詢、雜湊衝突-面試題

雜湊表查詢、雜湊衝突-面試題

雜湊查詢是面試中常見的問題。本文為自己梳理一下知識點。

對於大多數查詢演算法,其查詢效率取決於查詢過程的比較次數。比如二叉查詢樹,二分查詢。而有一種查詢不需要經過元素間的比較,而直接讓表中資料元素的關鍵字與其在記憶體中的儲存位置之間建立關係,在查詢時直接由關鍵字獲得資料元素的位置 。這就是雜湊表查詢。雜湊查詢特別適用於集合元素無明顯關係的集合。

雜湊表

雜湊儲存的基本思想是以關鍵字(key)為自變數,通過雜湊函式或雜湊(Hash)函式,計算出函式值(雜湊地址),作為資料元素的地址,並將資料元素存入相應地址的儲存單元中。查詢時再根據要查詢的關鍵字使用同樣的雜湊函式計算出雜湊地址,然後直接到相應的儲存單元中取出元素即可。

例:假設有一個集合:S={16,76,63,57,40},使用Hash法儲存該集合。現選取雜湊函式:h(K)=K%m. 即關鍵字值對m(正整數)取餘作為雜湊地址。本例中集合元素個數n等於5,為了能他們的使雜湊值不重複,這裡m可以取11.每個元素分別計算雜湊地址得:

h(16) = 16%11 = 5

h(57) = 57%11 = 2

… …

h(40) = 40%11 = 7

產生雜湊表如下圖:

hash

在查詢時,同樣對查詢關鍵字進行一次雜湊函式,所得值即為元素所有地址。本例中若要查詢16,h(16)=5,在地址(下標)位置取出元素即可。

對於含有n個數據元素的集合,只要m(儲存單元的個數)足夠大,總能找到關鍵字與雜湊地址一一對應。比如,最大關鍵字為m,此時可以分配m個儲存單元,雜湊函式選取h(key)=key,但如果集合元素不是連續的(通常不會是連續的),就會造成巨大的儲存空間浪費,甚至不可能分配到這麼大的空間。

雜湊衝突

由於儲存空間有限,也避免空間的浪費,通常取雜湊地址集合要少於關鍵字集合(關鍵字的取值空間),因此經過雜湊函式變換後,可能會出現不同的關鍵字對映到同一個雜湊地址上,這種現象稱為雜湊衝突。比如在上面例子中,若插入27至集合中,h(27)= 27%11 = 5,雜湊值就會與16的雜湊地址相同。

實際上衝突是不可避免的,只能儘可能的減少並且採取一定的策略解決衝突。綜上,使用雜湊表需要解決兩個問題:

(1) 構造合適的雜湊函式,儘可能減少衝突。

(2) 制定好應對衝突的方案。

常用的雜湊函式

在實際工作中根據不同的情況採用不同的雜湊函式,通常考慮的因素有:

(1)計算雜湊函式所需要的時間

(2)關鍵字的長度

(3)雜湊表的大小

(4)關鍵字的分佈情況

(5)記錄的查詢頻率

1.取餘法

該方法以一個略不天雜湊地址集合中地址個數m的質數去除關鍵字,取餘數作為雜湊地址。即


    H(key) = key%p,(p<=m)

使用取餘法選取的p非常重要,若選取不當,會造成嚴重的衝突。比如p=2^k或者p=10^k,雖然計算容易,但本質上只使用了key的幾個位(右移位運算),沒有充分利用關鍵字的特徵,會使雜湊地址分佈不均勻,易造成衝突。數學計算表明,p最好是一個小於中等於m的某個最大素數(此時求最大素數的演算法就有應用場景了)。

2.直接地址法

取關鍵字的線性函式為雜湊函式。即:


    H(key) = a*key +b (a,b為常數)

直接地址法(線性地址法)的特點是雜湊函式簡單,並且對不同的關鍵字不會產生衝突。但在實際問題中應用很少,原因是關鍵字集合的元素往往是離散的,而且關鍵字集合通常比雜湊地址集合大,用此方法會造儲存空間大量浪費。

3.數字分析法

對於關鍵字的位數比儲存區域的地址碼位數多的情況,可以採取對關鍵字的各位進行分析,丟掉分佈不均勻的位,留下分佈均勻的位作為雜湊地址,這種方法稱為數字分析法。

數字分析法的特點是雜湊函式依賴全體關鍵字集合,對不同的關鍵字,所保留的地址可能不同。此方法僅適用於能預先估計出全體關鍵字的每一位數字出現的頻度的情況。

4.摺疊法

摺疊法是將關鍵字自左到右分成位數相同的幾部分,最後一部分位數可以不同,然後將這幾部分疊加求和,並按雜湊表的表長,取最後的幾位作為雜湊地址。常用的疊加方法有兩種:

(1) 移位疊加法,將分割後的各部分最低部對齊,求和

(2) 間界疊加法,從一端向另一端沿分割界來回摺疊,然後對齊最後一位,求和。

對於數位比較多且每一位符號分佈均勻的關鍵字可以採用此方法求雜湊地址。

5.平方取中法

平方取中法的演算法是取關鍵字平方的中間幾位作為雜湊地址。此方法取得的雜湊地址同關鍵字每一位都有關,使得雜湊地址具有較好的分散性。平方取中法適用於關鍵字中的每一位取值都不夠分散或者較分散的位數小於雜湊地址所需要的位數的情況。

6.隨機數法

取關鍵字的隨機函式值作為其雜湊地址關鍵字,即H(key)=random(key),random為固定演算法的隨機函式,當關鍵字長度不相等時,此方式比較適用。

處理衝突的方法

合適的雜湊函式可以減少衝突,但衝突是不可避免的,需要合理的處理衝突方法。

1.開放定址法

開放定址法處理衝突的基本思想是當衝突發生時,形成一個地址序列,沿著這個序列逐個探測,直到找到一個“空”的開放地址,將發生衝突的關鍵字值存入到該地址中。開放地址法可以表示為:


    Hi = (H(key)+di)%m    (i=1,2,...k(k<=m-1)

H(key)是關鍵字key的雜湊函式,m為雜湊表長,di為每次再探測時的地址增量。地址增量的取法主要有線性探測法、二次探測法和雙雜湊函式探測法。

2.鏈地址法

3.公共溢位區法

4.再雜湊法

(未完待續)