散列沖突(哈希碰撞)的解決辦法


散列沖突(哈希碰撞)的解決辦法

    相關概念

    哈希算法(散列函數)

    哈希算法(散列算法)是信息存儲和查詢所用的一項基本技術,它是一種基於Hash函數的文件構造方法,可實現對記錄的快速隨機存取。它把給定的任意長關鍵字映射為一個固定長度的哈希值,一般用於鑒權、認證、加密、索引等。其主要優點是運算簡單,預處理時間較短,內存消耗低,匹配查找速度比較快,便於維護和刷新,支持匹配規則數多等。

    什么是哈希碰撞(散列沖突)

    Hash算法並不完美,有可能兩個不同的原始值在經過哈希運算后得到同樣的結果, 這樣就是哈希碰撞。

    解決辦法

    1、開放定址法

    所謂的開放定址法就是一旦發生了沖突,就去尋找下一個空的散列地址,只要散列表足夠大,空的散列地址總能找到,並將記錄存入。

    fi(key)=(f(key)+di)MOD m (di=1,2,3,…,m-1)

    1)線性探測法

    di=1,2,3,…,m-1

   這種方法的特點是:沖突發生時,順序查看表中下一單元,直到找出一個空單元或查遍全表。

   我們把這種解決沖突的開放地址法稱為線性探測法。

    2)二次探測法

    fi(key)=(f(key)+di)MOD m (di=1²,-1²,2²,-2²,…,q²,-q² (q<=m/2 )

    這種方法的特點是:沖突發生時,在表的左右進行跳躍式探測,比較靈活。

    增加平方運算的目的是為了不讓關鍵字都聚集在某一塊區域。我們稱這種方法為二次探測法。

    3)隨機探測法

   還有一種方法是,在沖突時,對於位移量di采用隨機函數計算得到,我們稱之為隨機探測法。

   fi(key)=(f(key)+di)MOD m (di是一個隨機數列 )

   總之,開放定址法只要在散列表未填滿時,總是能找到不發生沖突的地址,是我們常用的解決沖突的辦法。

    2、再散列函數法

    事先准備多個散列函數:

    fi(key)=RHi(key)( i=1,2,…,k)

    當哈希地址Hi=RH1(key)發生沖突時,再計算Hi=RH2(key)……,直到沖突不再產生。這種方法不易產生聚集,但增加了計算時間。

    3、鏈地址法(拉鏈法)

    思路還可以再換一換,為什么有沖突就非要換地方呢,我們直接就在原地處理行不行呢?於是我們就有了鏈地址法。

    將所有關鍵字為同義詞的記錄存儲在一個單鏈表中,我們稱這種表為同義詞子表,在散列表中只存儲所有同義詞子表的頭指針。

    對於關鍵字集合{12,67,56,16,25,37, 22,29,15,47,48,34},我們用前面同樣的12為除數,進行除留余數法:

     

   此時,已經不存在什么沖突換址的問題,無論有多少個沖突,都只是在當前位置給單鏈表增加結點的問題。

   拉鏈法解決沖突的做法是:將所有關鍵字為同義詞的結點鏈接在同一個單鏈表中。若選定的散列表長度為m,則可將散列表定義為一個由m個頭指針組成的指針數組T[0..m-1]。凡是散列地址為i的結點,均插入到以T[i]為頭指針的單鏈表中。T中各分量的初值均應為空指針。在拉鏈法中,裝填因子α可以大於 1,但一般均取α≤1。

   鏈地址法對於可能會造成很多沖突的散列函數來說,提供了絕不會出現找不到地址的保障,當然,這也就帶來了查找時需要遍歷單鏈表的性能損耗。

   4、建立公共溢出區

    這種方法的基本思想是:將哈希表分為基本表和溢出表兩部分,凡是和基本表發生沖突的元素,一律填入溢出表。

    在查找時,對給定值通過散列函數計算出散列地址后,先與基本表的相應位置進行對比,如果相等,則查找成功;如果不相等,則到溢出表去進行順序查找。如果相對於基本表而言,有沖突的數據很少的情況下,公共溢出區的結構對查找性能來說還是非常高的。


免責聲明!

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



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