哈希之閉散列(線性探測/二次探測)
哈希開散列
什麼是哈希
如果構造一種結構,通過某種函數(hashFunc)使元素的存儲位置與它的關鍵碼之間能夠建立一一映射的關係,那麼查找時通過該函數可以很快找到該元素。
- 插入元素時:根據待插入元素的關鍵碼,以此函數計算出該元素的位置的存儲位置並按此位置進行存放。
- 搜索元素時:對元素的關鍵碼進行同樣的計算,把求得的函數值當做元素的存儲位置,在結構中按此位置元素比較,若關鍵碼相等,則搜索成功。
這種方式即爲哈希方法,哈希方法中使用的轉換函數稱爲哈希函數,構造出來的結構稱爲哈希表。
哈希衝突
不同的關健字通過相同哈希函數計算出相同的哈希地址,該現象稱爲哈希衝突或哈希碰撞,把具有不同關鍵碼而具有相同哈希地址的數據元素成爲“同義詞”。
如上圖,在往哈希表裏放個14就會產生衝突,因爲該位置已經有數字6了。
哈希函數
引起哈希衝突的一個可能原因就是哈希函數設置的不合理。
哈希函數設計原則:
- 哈希函數的定義域必須包括需要存儲的全部關鍵碼,而如果散列表允許有m個地址,其值域必須在0到m-1之間
- 哈希函數計算出來的地址能夠均勻分佈在整個函數空間中
- 哈希函數應該比較簡單。
常見的哈希函數
- 直接定址法
取關鍵字的某個線性函數爲散列地址:Hash(key) = A*key+B
優點:均勻、簡單
缺點:需要實現直到關鍵字的分佈情況
適合查找比較小且連續的情況 - 除留餘數法
設散列表中允許的地址數爲m,取一個不大於m,但最接近或者等於m的質數作爲除數,按照哈希函數:Hash(key)= key%p(p<=m),將關鍵碼轉換爲哈希地址。 - 平方取中法
假設關鍵字爲1234,對它平方就是1522756,抽取中間的3位227作爲哈希地址;
再比如關鍵字爲4321,對它平方就是18671041,抽取中間的3位671(或710)作爲哈希地址
平方取中法比較適合:不知道關鍵字的分佈,而位數又不是很大的情況 - 摺疊法
摺疊法是將關鍵字從左到右分割成位數相等的幾部分(最後一部分位數可以短些),然後將這幾部分疊加求和,並按散列表表
長,取後幾位作爲散列地址
摺疊法適合事先不需要知道關鍵字的分佈,適合關鍵字位數比較多的情況 - 隨機數法
選擇一個隨機函數,取關鍵字的隨機函數值爲它的哈希地址,即H(key) = random(key),其中random爲隨機數函數
通常應用於關鍵字長度不等時採用此法 - 數學分析法
設有n個d位數,每一位可能有r種不同的符號,這r種不同的符號在各位上出現的頻率不一定相同,可能在某些位上分佈比較均
勻,每種符號出現的機會均等,在某些位上分佈不均勻只有某幾種符號經常出現。可根據散列表的大小,選擇其中各種符號分
布均勻的若干位作爲散列地址。
數字分析法通常適合處理關鍵字位數比較大的情況,如果事先知道關鍵字的分佈且關鍵字的若干位分佈較均勻的情況
處理哈希衝突
閉散列
閉散列:也叫開放地址法,當發生哈希衝突時,如果哈希表未被裝滿,說明在哈希表中必然還有空位置,那麼可以把key存放到表中
“下一個” 空
位中去。
- 線性探測
一旦衝突必須要找出下一個空餘位置,線性探測找的處理爲:從發生衝突的位置開始,依次繼續向後探測,直到找到空位置爲止。
採用閉散列處理哈希衝突時,不能隨便物理刪除哈希表中已有的元素,若直接刪除元素會影響其他元素的搜索。
採用線性探測,實現起來非常簡單,缺陷是:
一旦發生哈希衝突,所有的衝突連在一起,容易產生數據“堆積”,即:不同關鍵碼佔據了可利用的空位置,使得尋找某關鍵碼的位置需要許多次比較,導致搜索效率降低。
- 二次探測
發生哈希衝突時,二次探查法在表中尋找“下一個”空位置的公式爲:
= ( + ) % m, = ( - ) % m, i = 1,2,3…, 是通過散列函數Hash(x)對元素的關鍵碼 key 進行計算得到的位置,m是表的大小。
研究表明:當表的長度爲質數且表裝載因子a不超過0.5時,新的表項一定能夠插入,而且任何一個位置都不會被探查兩次。因此只此要表中有一半的空位置,就不會存在表滿的問題。在搜索時可以不考慮表裝滿的情況,但在插入時必須確保表的裝載因子a不超過0.5;如果超出必須考慮增容
開散列
開散列法又叫鏈地址法(開鏈法)。
開散列法:首先對關鍵碼集合用散列函數計算散列地址,具有相同地址的關鍵碼歸於同一子集合,每一個子集合稱爲一個桶,各個
桶中的元素通過一個單鏈錶鏈接起來,各鏈表的頭結點存儲在哈希表中
擴展
素數表
// 使用素數表對齊做哈希表的容量,降低哈希衝突
const int _PrimeSize = 28;
static const unsigned long _PrimeList [_PrimeSize] =
{
53ul, 97ul, 193ul, 389ul, 769ul,
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
1610612741ul, 3221225473ul, 4294967291ul
};