哈希表

 1.哈希表的定義

哈希表:根據關鍵碼值(key value)直接進行訪問的數據結構,也就是說,它經過把關鍵碼值映射到表中一個位置來訪問記錄,以加快查找速度,這個映射函數叫作哈希函數,存放記錄的數組叫作哈希表。算法

給定表M,存在函數f(key),對任意給定的關鍵字值key,代入函數後若能獲得包含該關鍵字的記錄在表中的地址,則稱表M爲哈希(Hash)表,函數f(key)爲哈希(Hash) 函數。數組

舉例:新華字典,我想要獲取「按」字詳細信息,去根據拼音an去查找拼音索引,首先去查an在字典的位置,獲得「安」,這個過程就是鍵碼映射。在公式裏,就是經過key去查找f(key)。其中,按就是關鍵字(key),f(key)就是字典索引,也就是哈希函數,查到的頁碼4就是哈希值。緩存

 

2.如何構造哈希表

根據設定的哈希函數f=H(key)和處理衝突的方法,將一組關鍵字映像到一個有限的連續的地址集上,並以關鍵字在地址集中的」象」做爲記錄在表中的存儲位置,這一映像過程,稱爲構造哈希表(散列表)。服務器

幾種常見的哈希函數(散列函數)構造方法

  • 直接定址法
    • 取關鍵字或關鍵字的某個線性函數值爲散列地址。
    • 即 H(key) = key 或 H(key) = a*key + b,其中a和b爲常數。
    • 好比
  • 除留餘數法 
    • 取關鍵字被某個不大於散列表長度 m 的數 p 求餘,獲得的做爲散列地址。對除數p的選擇很重要,若p選的很差,則很容易產生同義詞。通常,將p選爲素數或不包含大於20的。
    • 即 H(key) = key % p, p < m。
    • 好比
  • 數字分析法
    • 當關鍵字的位數大於地址的位數,對關鍵字的各位分佈進行分析,選出分佈均勻的任意幾位做爲散列地址。
    • 僅適用於全部關鍵字都已知的狀況下,根據實際應用肯定要選取的部分,儘可能避免發生衝突。
    • 好比
  • 平方取中法
    • 先計算出關鍵字值的平方,而後取平方值中間幾位做爲散列地址。
    • 隨機分佈的關鍵字,獲得的散列地址也是隨機分佈的。
    • 好比
  • 摺疊法(疊加法)
    • 將關鍵字分爲位數相同的幾部分,而後取這幾部分的疊加和(捨去進位)做爲散列地址。
    • 用於關鍵字位數較多,而且關鍵字中每一位上數字分佈大體均勻。
    • 好比
  • 隨機數法
    • 選擇一個隨機函數,把關鍵字的隨機函數值做爲它的哈希值。
    • 一般當關鍵字的長度不等時用這種方法。

構造哈希函數的方法不少,實際工做中要根據不一樣的狀況選擇合適的方法,總的原則是儘量少的產生衝突網絡

一般考慮的因素有關鍵字的長度和分佈狀況、哈希值的範圍等。數據結構

如:當關鍵字是整數類型時就能夠用除留餘數法;若是關鍵字是小數類型,選擇隨機數法會比較好。分佈式

 

3.哈希衝

若key1≠key2, 而f(key1)=f(key2), 則這種現象稱爲衝突,且key1和key2對哈希函數f來講是同義詞。
函數

 

4. 哈希衝突解決方法

1.開放定址法(線性探測再散列,二次探測再散列,僞隨機探測再散列)

用開放定址法解決衝突的作法是:性能

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

簡單的說:當衝突發生時,使用某種探查(亦稱探測)技術在散列表中尋找下一個空的散列地址,只要散列表足夠大,空的散列地址總能找到。spa

按照造成探查序列的方法不一樣,可將開放定址法區分爲線性探查法、二次探查法、雙重散列法等。

a.線性探查法

hi=(h(key)+i) % m ,0 ≤ i ≤ m-1

基本思想是:
探查時從地址 d 開始,首先探查 T[d],而後依次探查 T[d+1],…,直到 T[m-1],此後又循環到 T[0],T[1],…,直到探查到 有空餘地址 或者到 T[d-1]爲止。

b.二次探查法

hi=(h(key)+i*i) % m,0 ≤ i ≤ m-1

基本思想是:
探查時從地址 d 開始,首先探查 T[d],而後依次探查 T[d+1^2],T[d+2^2],T[d+3^2],…,等,直到探查到 有空餘地址 或者到 T[d-1]爲止。

缺點是沒法探查到整個散列空間。

c.雙重散列法

hi=(h(key)+i*h1(key)) % m,0 ≤ i ≤ m-1

基本思想是:
探查時從地址 d 開始,首先探查 T[d],而後依次探查 T[d+h1(d)], T[d + 2*h1(d)],…,等。

該方法使用了兩個散列函數 h(key) 和 h1(key),故也稱爲雙散列函數探查法。

定義 h1(key) 的方法較多,但不管採用什麼方法定義,都必須使 h1(key) 的值和 m 互素,才能使發生衝突的同義詞地址均勻地分佈在整個表中,不然可能形成同義詞地址的循環計算。

該方法是開放定址法中最好的方法之一。

2.鏈地址法(拉鍊法)

拉鍊法解決衝突的作法是: 
將全部關鍵字爲同義詞的結點連接在同一個單鏈表中。

若選定的散列表長度爲 m,則可將散列表定義爲一個由 m 個頭指針組成的指針數組 T[0..m-1] 。

凡是散列地址爲 i 的結點,均插入到以 T[i] 爲頭指針的單鏈表中。
T 中各份量的初值均應爲空指針。

在拉鍊法中,裝填因子 α 能夠大於 1,但通常均取 α ≤ 1。

3.再哈希法

這種方法是同時構造多個不一樣的哈希函數: 
Hi=RH1(key) i=1,2,…,k 
當哈希地址Hi=RH1(key)發生衝突時,再計算Hi=RH2(key)……,直到衝突再也不產生。這種方法不易產生彙集,但增長了計算時間。

4.創建一個公共溢出區

 將哈希表分爲基本表和溢出表兩部分,凡是和基本表發生衝突的元素,一概填入溢出表。

 

5.哈希的應用

  • 哈希表
  • 分佈式緩存

哈希表(散列表)

哈希表(hash table)是哈希函數最主要的應用。

哈希表是實現關聯數組(associative array)的一種數據結構,普遍應用於實現數據的快速查找。

用哈希函數計算關鍵字的哈希值(hash value),經過哈希值這個索引就能夠找到關鍵字的存儲位置,即桶(bucket)。哈希表不一樣於二叉樹、棧、序列的數據結構通常狀況下,在哈希表上的插入、查找、刪除等操做的時間複雜度是 O(1)。

查找過程當中,關鍵字的比較次數,取決於產生衝突的多少,產生的衝突少,查找效率就高,產生的衝突多,查找效率就低。所以,影響產生衝突多少的因素,也就是影響查找效率的因素。
影響產生衝突多少有如下三個因素:

哈希函數是否均勻;
處理衝突的方法;
哈希表的加載因子。
哈希表的加載因子和容量決定了在何時桶數(存儲位置)不夠,須要從新哈希。

加載因子太大的話桶太多,遍歷時效率變低;太大的話頻繁 rehash,致使性能下降。因此加載因子的大小須要結合時間和空間效率考慮。

在 HashMap 中的加載因子爲 0.75,即四分之三。

分佈式緩存

網絡環境下的分佈式緩存系統通常基於一致性哈希(Consistent hashing)。簡單的說,一致性哈希將哈希值取值空間組織成一個虛擬的環,各個服務器與數據關鍵字K使用相同的哈希函數映射到這個環上,數據會存儲在它順時針「遊走」遇到的第一個服務器。可使每一個服務器節點的負載相對均衡,很大程度上避免資源的浪費。

在動態分佈式緩存系統中,哈希算法的設計是關鍵點。使用分佈更合理的算法可使得多個服務節點間的負載相對均衡,能夠很大程度上避免資源的浪費以及部分服務器過載。 使用帶虛擬節點的一致性哈希算法,能夠有效地下降服務硬件環境變化帶來的數據遷移代價和風險,從而使分佈式緩存系統更加高效穩定。

 

轉:重溫數據結構:哈希 哈希函數 哈希表

相關文章
相關標籤/搜索