通過構造效能良好的雜湊函式,可以減少衝突,但一般不可能完全避免衝突,因此解決衝突是雜湊法的另乙個關鍵問題。建立雜湊表和查詢雜湊表都會遇到衝突,兩種情況下解決衝突的方法應該一致。下面以建立雜湊表為例,說明解決衝突的方法。常用的解決衝突方法有以下四種:
這種方法也稱再雜湊法,其基本思想是:當關鍵字key的雜湊位址p=h(key)出現衝突時,以p為基礎,產生另乙個雜湊位址p1,如果p1仍然衝突,再以p為基礎,產生另乙個雜湊位址p2,…,直到找出乙個不衝突的雜湊位址pi ,將相應元素存入其中。這種方法有乙個通用的再雜湊函式形式:
hi=(h(key)+di)% m i=1,2,…,n
其中h(key)為雜湊函式,m 為表長,di稱為增量序列。增量序列的取值方式不同,相應的再雜湊方式也不同。主要有以下三種:
dii=1,2,3,…,m-1
di=12,-12,22,-22,…,k2,-k2 ( k<=m/2 )
這種方法的特點是:衝突發生時,在表的左右進行跳躍式探測,比較靈活。
di=偽隨機數序列。
具體實現時,應建立乙個偽隨機數發生器,(如i=(i+p) % m),並給定乙個隨機數做起點。
如果用線性探測再雜湊處理衝突,下乙個雜湊位址為h1=(3 + 1)% 11 = 4,仍然衝突,再找下乙個雜湊位址為h2=(3 + 2)% 11 = 5,還是衝突,繼續找下乙個雜湊位址為h3=(3 + 3)% 11 = 6,此時不再衝突,將69填入5號單元。
如果用二次探測再雜湊處理衝突,下乙個雜湊位址為h1=(3 + 12)% 11 = 4,仍然衝突,再找下乙個雜湊位址為h2=(3 - 12)% 11 = 2,此時不再衝突,將69填入2號單元。
如果用偽隨機探測再雜湊處理衝突,且偽隨機數序列為:2,5,9,……..,則下乙個雜湊位址為h1=(3 + 2)% 11 = 5,仍然衝突,再找下乙個雜湊位址為h2=(3 + 5)% 11 = 8,此時不再衝突,將69填入8號單元。
這種方法是同時構造多個不同的雜湊函式:
hi=rh1(key) i=1,2,…,k
當雜湊位址hi=rh1(key)發生衝突時,再計算hi=rh2(key)……,直到衝突不再產生。這種方法不易產生聚集,但增加了計算時間。
這種方法的基本思想是將所有雜湊位址為i的元素構成乙個稱為同義詞鏈的單鏈表,並將單鏈表的頭指標存在雜湊表的第i個單元中,因而查詢、插入和刪除主要在同義詞鏈中進行。鏈位址法適用於經常進行插入和刪除的情況。
這種方法的基本思想是:將雜湊表分為基本表和溢位錶兩部分,凡是和基本表發生衝突的元素,一律填入溢位表。
1)優點: ①對於記錄總數頻繁可變的情況,處理的比較好(也就是避免了動態調整的開銷) ②由於記錄儲存在結點中,而結點是動態分配,不會造成記憶體的浪費,所以尤其適合那種記錄本身尺寸(size)很大的情況,因為此時指標的開銷可以忽略不計了 ③刪除記錄時,比較方便,直接通過指標操作即可
2)缺點: ①儲存的記錄是隨機分布在記憶體中的,這樣在查詢記錄時,相比結構緊湊的資料型別(比如陣列),雜湊表的跳轉訪問會帶來額外的時間開銷 ②如果所有的 key-value 對是可以提前預知,並之後不會發生變化時(即不允許插入和刪除),可以人為建立乙個不會產生衝突的完美雜湊函式(perfect hash function),此時封閉雜湊的效能將遠高於開放雜湊 ③由於使用指標,記錄不容易進行序列化(serialize)操作
1)優點: ①記錄更容易進行序列化(serialize)操作 ②如果記錄總數可以預知,可以建立完美雜湊函式,此時處理資料的效率是非常高的
2)缺點: ①儲存記錄的數目不能超過桶陣列的長度,如果超過就需要擴容,而擴容會導致某次操作的時間成本飆公升,這在實時或者互動式應用中可能會是乙個嚴重的缺陷 ②使用探測序列,有可能其計算的時間成本過高,導致雜湊表的處理效能降低 ③由於記錄是存放在桶陣列中的,而桶陣列必然存在空槽,所以當記錄本身尺寸(size)很大並且記錄總數規模很大時,空槽占用的空間會導致明顯的記憶體浪費 ④刪除記錄時,比較麻煩。比如需要刪除記錄a,記錄b是在a之後插入桶陣列的,但是和記錄a有衝突,是通過探測序列再次跳轉找到的位址,所以如果直接刪除a,a的位置變為空槽,而空槽是查詢記錄失敗的終止條件,這樣會導致記錄b在a的位置重新插入資料前不可見,所以不能直接刪除a,而是設定刪除標記。這就需要額外的空間和操作。
資料結構 解決hash衝突的三個方法
目錄 開放定址法 線性探測再雜湊 二次探測再雜湊 偽隨機探測再雜湊 再雜湊法 鏈位址法 建立公共溢位區 優缺點開放雜湊 open hashing 拉鍊法 針對桶鏈結構 封閉雜湊 closed hashing 開放定址法 通過構造效能良好的雜湊函式,可以減少衝突,但一般不可能完全避免衝突,因此解決衝突...
hash,解決hash衝突的方法
數字分析法 平方取中法 除留餘數法 偽隨機數法 線性探測 二次探測 偽隨機數探測 拉鍊探測。如果負載因子是預設的0.75,hashmap 16 的時候,佔16個記憶體空間,實際上只用到了12個,超過12個就擴容。如果負載因子是1的話,hashmap 16 的時候,佔16個記憶體空間,實際上會填滿16...
解決Hash衝突的方法
線性再雜湊法是形式最簡單的處理衝突的方法。插入元素時,如果發生衝突,演算法會簡單的從該槽位置向後迴圈遍歷hash表,直到找到表中的下乙個空槽,並將該元素放入該槽中 會導致相同hash值的元素挨在一起和其他hash值對應的槽被占用 查詢元素時,首先雜湊值所指向的槽,如果沒有找到匹配,則繼續從該槽遍歷h...