Hash表算法詳解


Hash表定義

散列表(Hash table,也叫哈希表),是根據關鍵字值(Key value)直接進行訪問的數據結構。也就是說,它通過把關鍵字(關鍵字通過Hash算法生成)映射到表中一個位置來訪問記錄,以加快查找的速度。這個映射函數叫做散列函數,存放記錄的數組叫做散列表。

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

Hash算法定義

哈希算法將任意長度的二進制值映射為較短的固定長度的二進制值,這個小的二進制值稱為哈希值。哈希值是一段數據唯一且極其緊湊的數值表示形式。如果散列一段明文而且哪怕只更改該段落的一個字母,隨后的哈希都將產生不同的值。要找到散列為同一個值的兩個不同的輸入,在計算上是不可能的,所以數據的哈希值可以檢驗數據的完整性。一般用於快速查找和加密算法。

關鍵字K生成常用方法

關鍵字生成的目標:構造沖突較低的散列地址,保證散列表中數據的離散度。大部分情況下,我們都不清楚關鍵字的分布,可以采取以下常用的啟發式散列算法。若我們清楚數據的分布,可以根據具體的分布情況來設計特定的散列算法。

除法散列法

取關鍵字被某個不大於散列表表長m的數p除后所得的余數為散列地址。對p的選擇很重要,一般取素數或m,若p選的不好,容易產生同義詞

公式:H(key) = key % p (p<=m)

平方散列法

當無法確定關鍵字中哪幾位分布較均勻時,可以先求出關鍵字的平方值,然后按需要取平方值的中間幾位作為哈希地址。這是因為:平方后中間幾位和關鍵字中每一位都相關,故不同關鍵字會以較高的概率產生不同的哈希地址。

公式:H(key) = ((key * Key) >> X) << Y

斐波那契(Fibonacci)散列法

和平方散列法類似,此種方法使用斐波那契數列的值作為乘數而不是自己。

  1. 對於16位整數而言,這個乘數是40503。
  2. 對於32位整數而言,這個乘數是2654435769。
  3. 對於64位整數而言,這個乘數是11400714819323198485。

公式:H(key) = ((key * 2654435769) >> X) << Y

隨機數法

選擇一隨機函數,取關鍵字的隨機值作為散列地址,通常用於關鍵字長度不同的場合。

公式:H(key) = Radmon(key)

處理碰撞

開放尋址法

開放尋址法把所有的元素都存放在散列表中,也就是每個表項包含動態集合的一個元素(元素可以為NULL)。

  1. 在開放尋址法中,當要插入一個元素時,可以連續地檢查散列表的個各項(連續檢查是可以通過不同的算法獲得偏移位),直到找到一個空槽來放置這個元素為止。
  2. 當查找一個元素時,要檢查所有的表項,直到找到所需的元素,或者最終發現元素不在表中。
  3. 在開放尋址法中,對散列表元素的刪除操作執行起來比較困難。當我們從槽i中刪除關鍵字時,不能僅將此位置元素置空。因為這樣做的話,會導致在無法判斷此位置是否有元素。應該用個特殊的值表示該元素已經刪除。

公式:Hi=(H(key) + di) MOD m , [i=1,2,…,k(k<=m-1)]

其中H(key)為散列函數,m為散列表長,di為增量序列,可有下列三種取法:

  1. di=1,2,3,…,m-1,稱線性探測再散列
  2. di=12,-12,22,-22,⑶2,…,±(k)2,(k<=m/2)稱二次探測再散列
  3. di=偽隨機數序列,稱偽隨機探測再散列

再散列法

產生碰撞時,再使用另一個散列函數計算地址,直到碰撞不再發生,這種方法不易產生“聚集”,但增加了計算時間(一個地址的產生可能會經過多個散列函數的計算)

公式:Hi=Hn(key), [n=1,2 ...,]

有一個包含一組哈希函數 H1...Hn 的集合。當需要從哈希表中添加或獲取元素時,首先使用哈希函數 H1。如果導致碰撞,則嘗試使用 H2,以此類推,直到 Hn。所有的哈希函數都與 H1 十分相似,不同的是它們選用的乘法因子。

拉鏈法

產生碰撞時,把哈希到同一個槽中的所有元素都放到一個鏈表中。拉鏈法采用額外的數據結構來處理碰撞,其將哈希表中每個位置(slot)都映射到了一個鏈表。

公共溢出區

建立一個公共溢出區,當發生碰撞時,把碰撞元素放到緩沖區。

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM