解決哈希衝突的幾種方法

Hash衝突的概念

哈希算法 的目的就是將一串很大的數據根據一定的規則轉換爲較小的數據。
把任意長度的二進制值串映射爲固定長度的二進制值串,這個映射的規則就是哈希算法,而通過原始數據映射之後得到的二進制值串就是哈希值
在這個轉換過程中,總會出現兩個不同的數據在經過哈希算法的計算後生成了相同的哈希值。這就是哈希衝突
哈希衝突帶來的影響:
在哈希表中,兩個不同數據的哈希值相同,那麼不論這兩個數據中任意一個先存放到指定位置之後,第二個數據都沒有地方可以存放了。所以設計哈希算法的時候一定要注意哈希衝突問題!

哈希算法滿足的幾點要求:

  1. 從哈希值不能反向推導出原始數據(所以哈希算法也叫單向哈希算法);
  2. 對輸入數據非常敏感,哪怕原始數據只修改了一個 Bit,最後得到的哈希值也大不相同;
  3. 散列衝突的概率要很小,對於不同的原始數據,哈希值相同的概率非常小;
  4. 哈希算法的執行效率要儘量高效,針對較長的文本,也能快速地計算出哈希值

常見的三種解決哈希衝突的方法

1. 開放地址法

爲產生衝突的地址Hash(key)求得一個地址序列:

H0,H1,H2,...,Hn        1  <= n <= m - 1 其中m爲表的大小

H0 = H(key) Hi = (H(key)+ di)% m  i=1,2,...n

形象地一句話來說,就是根據增量di不斷地往後找可以存放的下標。

增量di可以有下面三種取值:

  • 線性取值,1,2,3…這樣,也就是從衝突位置不斷往後找下一個可以存放的下標
  • 二次取值,1,4,9…這樣,也就是從衝突位置不斷往後找x的二次方的下標,其中x從1開始線性增大
  • 隨機取值,di可以去任意隨機值,隨機找一個

開放定製法有很明顯的缺點
元素不能刪除
當哈希表中元素越來越滿時,效率明顯下降

2. 二次哈希法

若通過一次哈希算法計算出來的結果相同,那麼久在原基礎上再用另外的哈希函數進行計算,直到不再產生相同的哈希值爲止。需要設計不同的哈希算法,類似於開放地址法;

3. 鏈地址法

每個下標中存的都是一個鏈表,相同哈希值的key直接往下標中的鏈表後面插入就行了
在這裏插入圖片描述
鏈地址法也是目前最常用的一種方法,尤其是當今的電腦性能較好時候。
但是也存在一定的缺陷:

  • 需要稍微多一點的空間來存放元素,因爲還要有一個指向下一個節點的指針
  • 每次探測也要花費較多的時間,因爲它需要間接引用指針,而不是直接訪問元素

目前稍微總結了一下,還有一些不完善,歡迎評論指出,而且可能不同的人有不同的命名法則,鏈地址法也稱拉鍊法,或者哈希桶。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章