1. 程式人生 > >散列表(雜湊表)(雜湊函式構造、處理衝突、查詢)

散列表(雜湊表)(雜湊函式構造、處理衝突、查詢)

什麼是雜湊表(散列表)?

雜湊表(Hash table,也叫散列表),是根據關鍵碼值(Key value)而直接進行訪問的資料結構。也就是說,它通過把關鍵碼值對映到表中一個位置來訪問記錄,以加快查詢的速度。這個對映函式叫做雜湊函式,存放記錄的陣列叫做散列表。 記錄的儲存位置 = f(關鍵字) 這裡的對應關係f稱為雜湊函式,又稱為雜湊(Hash函式),採用雜湊技術將記錄儲存在一塊連續的儲存空間中,這塊連續儲存空間稱為散列表或雜湊表(Hash table)。

一、雜湊函式的構造方法

1、直接定址法

關鍵碼本身和地址之間存在某個線性函式關係時,雜湊函式取為關鍵碼的線性函式,即:H(key)=a*key+b,a、b均為常數。 在這裡插入圖片描述

這樣的雜湊函式優點就是簡單、均勻,也不會產生衝突,但問題是這需要事先知道關鍵字的分佈情況,適合査找表較小且連續的情況。由於這樣的限制,在現實應用中,直接定址法雖然簡單,但卻並不常用。

2、數字分析法

假設關鍵碼完全已知,且每個關鍵碼都是以某個數r為基數(例以10為基數的十進位制數)的值,則關鍵碼中若干位恰能構成分佈比較均勻的雜湊地址空間時,可取關鍵碼的若干位的組合作為雜湊地址。

3、除留餘數法

通過選擇適當的正整數p,按計算公式H(K)=K mod p來計算關鍵碼K的雜湊地址。若關鍵碼個數為n,散列表表長為m(一般m>=n),通常選p為小於或等於表長m的最大素數或不包含小於20的質因子的合數,一般也要求p >= n。這種方法計算最簡單,也不需根據全部關鍵碼的分佈情況研究如何從中析取資料,最常用。

4、平方取中法

將關鍵碼K平方,取K^2中間幾位作為其雜湊地址H(K)的值。 假如有以下關鍵字序列{421,423,436},平方之後的結果為{177241,178929,190096},那麼可以取{72,89,00}作為Hash地址。

5、摺疊法

將關鍵碼從低位到高位(或從高位到低位)分割成位數相等的幾段,最後一段可以短些,然後將這些段構成的數值按照某種疊加方法求和。最後,在雜湊地址範圍限制下,取求和結果的最後幾位作為關鍵碼的雜湊函式值。疊加方法: (1)移位疊加:將各段數值最後一位對齊相加; (2)間界疊加:從各個數值段的一端到另一端來回摺疊後(奇數段位正序,偶數為倒序),以最後一位對齊後相加。

6、隨機數法

採用隨機函式作為雜湊函式H(Key)=random(Key),其中random為隨機函式。 當關鍵碼長度不等時,採用該方法較恰當。

二、衝突的處理方法

1、開放定址法(建立閉散列表)

開放定址(具體的方法點連結)指散列表的地址對任何記錄資料都是開放的,即可儲存使用。但散列表長度一旦確定,總的可用地址是有限的。閉散列表表長不小於所需儲存的記錄數,發生衝突總能找到空的雜湊地址將其存入。查詢時,按照一種固定的順序檢索散列表中的相應項,直到找到一個關鍵字等於k或找到一個空單元將k插入,故是動態查詢結構。

2、拉鍊法(鏈地址法、建立開散列表)

將所有雜湊地址相同的記錄儲存在同一個單鏈表中,該單鏈表為同義詞單鏈表,或同義詞子表。該單鏈表頭指標儲存在散列表中。散列表就是個指標陣列,下標就是由關鍵碼用雜湊函式計算出的雜湊地址。初始,指標陣列每個元素為空指標,相當於所有單鏈表頭指標為空,以後每掃描到一條記錄,按其關鍵碼的雜湊地址,在相應的單鏈表中加入含該記錄的節點。開散列表容量可很大,僅受記憶體容量的限制。例:具體的關鍵字列表為(19,14,23,01,68,20,84,27,55,11,10,79),則雜湊函式為H(key)=key MOD 13。則採用除留餘數法和鏈地址法後得到的預想結果應該為: 在這裡插入圖片描述

三、散列表上的查詢

時間複雜度分析 查詢成功時的平均查詢長度ASLsucc、查詢不成功時的平均查詢長度ASLunsucc。 一般情況下,處理衝突方法相同的散列表,其查詢成功時的平均查詢長度依賴於散列表的裝填因子(負載因子):a=表中填入的記錄數/雜湊表長度。 a越小,發生衝突的可能性越小,反之,a越大,表中已填入記錄越多,再填記錄時,發生衝突的可能性越大,查詢時給定值需與之進行比較關鍵碼數目越多。 在這裡插入圖片描述