01哈希表

1. Hash Table

​ 咱們都知道,二叉樹、紅黑樹等數據結構,它們的查找都是先從根節點開始查找,從節點取出數據或者索引與查找值進行比較。數組

​ 那麼,有沒有一種函數H,根據這個函數和查找關鍵字 Key,能夠直接肯定查找值所在的位置,而不須要一個個比較。這樣叫「預先知道」 Key 所在的位置,直接找到數據,提高效率。即:數據結構

地址index = H(key)dom

說白了,hash函數功能就是根據 key 計算出應該存儲地址的位置,而哈希表是基於哈希函數創建的一種查找表。函數

2. 哈希函數的構造方法

​ 根據前人經驗,統計出集中經常使用 hash 函數構造方法設計

2.1. 直接定製法

​ 哈希函數爲關鍵字的線性函數,如 H(key) = a * key + b,這種構造方法比較簡單,均勻。可是有很大限制,僅限與地址大小 = 關鍵字集合的狀況。指針

2.2. 數字分析法

​ 假設關鍵字集合中的每一個關鍵字 key 都是由s位數字組成(k1,k2,……,kn),分析 key 中的全體數據,並從中提取分佈均勻的若干位或他們的組合構成全體。code

​ 使用舉例:假設要保存的集合中 key 由 5 位不一樣的數字構成。而且這些數字分佈均勻,咱們能夠提取其中一位,表明數據保存的地址。H(key) = key % 100000。索引

​ 此種方法一般用於數字位數較長的狀況,要求數字存在必定的規律,其次必須知道數字的分佈狀況。hash

2.3. 平方取中法

​ 若是關鍵字的每一位都有某些數字重複出現頻率很高的現象,能夠先求關鍵字的平方值,經過平方擴大差別,然後取中間數位做爲最終存儲地址。table

​ 使用舉例:

​ 好比:key = 1234 1234^2 = 1522756 取 227 做hash地址

​ 好比:key = 4321 4321^2 = 18671041 取 671 做hash地址

​ 這種方法適合事先不知道數據而且數據長度較小的狀況。

2.4. 摺疊法

​ 若是數字的位數不少,能夠將數字分割爲幾個部分,取他們的疊加和做爲hash地址。

​ 使用舉例:

​ 好比 key=123 456 789

​ 咱們能夠取 1368(123+456+789=1368) 做爲 hash 地址。

該方法適用於數字位數較多且事先不知道數據分佈的狀況。
2.5. 除留餘數法(最經常使用)

​ H(key)=key MOD p (p<=m m爲表長) 很明顯,如何選取p是個關鍵問題。

​ 使用舉例
好比咱們存儲3 6 9,那麼p就不能取3
由於 3 MOD 3 == 6 MOD 3 == 9 MOD 3
p應爲不大於m的質數或是不含20如下的質因子的合數,這樣能夠減小地址的重複(衝突)

​ 好比key = 7,39,18,24,33,21 時取表長m爲9 p爲7 那麼存儲以下:

index 0 1 2 3 4 5 6 7 8
Key 7 21(衝突後移) 24 39 18(衝突後移) 33(衝突後移)
2.6. 隨機數法

​ H(key)= random (key) 取關鍵字的隨機函數爲它們的散列地址。

哈希函數設計的考慮因素
  • 計算散列地址所須要的時間(即 hash 函數自己不要太複雜)
  • 關鍵字的長度
  • 表長
  • 關鍵字分佈是否均勻,是否有規律可循
  • 設計的 hash 函數在充分考慮了以上因素的狀況下儘可能減小衝突。

3. 哈希衝突

​ 上面已經提到,不一樣 key 經過 hash 函數產生相同的地址,即 H(key1) == H (key2),此時,key1 和 key2 就發生了 hash 衝突。

4. 哈希衝突的解決方案

​ 無論 hash 函數設計的如何巧妙,總會有特殊的 key 致使 hash 衝突, 特別是對童泰查找表來講。

4.1. 開放定製法

​ 首先有一個H(key)的哈希函數。
若是H(key1)= H(keyi),那麼 keyi 存儲位置 Hi = (H(key)+di) MOD m。其中 m 是表長。

di 有三種取法:

  • 線性探測再散列: di = c * i。
  • 平方探測再散列: di = i * i。
  • 隨機探測再散列:di 是 一個僞隨機數。
4.2. 鏈地址法

​ 產生hash衝突後在存儲數據後面加一個指針,指向後面衝突的數據。

image

4.3 公共溢出區法

​ 創建一個特殊存儲空間,專門存放衝突的數據。此種方法適用於數據和衝突較少的狀況。

4.4. 再散列法

​ 準備若干個hash函數,若是使用第一個hash函數發生了衝突,就使用第二個hash函數,第二個也衝突,使用第三個……

5. 哈希表的查找

5.1. 哈希表查找過程

​ 查找過程和造表過程一致,假設採用開放定址法處理衝突,則查找過程爲:

  • 對於給定的 key,計算 hash 地址 index = H(key)。

  • 若是數組 arr[index] == null, 則查找不成功;

  • 若是數組 arr[index] == key,則查找成功;

  • 若是 (arr[index] != null && arr[index] != key),使用 hash 衝突解決方法求下一個地址,直到(arr[index] == null || arr[index] == key)。

5.2. 哈希表的查找效率

​ 決定 hash 表查找的 ASL 因素:

  • 選用的 hash 函數
  • 選用的處理衝突的方法
  • hash 表的飽和度, 裝載因子 α = n/m (n 表示實際裝載數據長度, m 爲表長)

相關文章
相關標籤/搜索