小結
-
散列函數構造方法:
- 1.直接定址法:H(key) = a*key + b
- 2.除留余數法:H(key) = key % p(p為不大於散列表表長,但最接近或等於表長的質數p)
- 3.數字分析法:選取r進制數數碼分布較為均勻的若干位作為散列地址
- 4.平方取中法:取關鍵字的平方值的中間幾位作為散列地址
- 5.折疊法:將關鍵字分割成位數相同的幾部分,然后取這幾部份的疊加和作為散列地址
-
處理沖突的方法:
- 1.開放定址法(閉哈希表):在沖突的哈希地址的基礎上進行處理,得到新的地址值。Hi = (H(key)+di) % m(m表示散列表表長,di為增量序列)
- 1)線性探測法:dii=1,2,3,…,m-1
- 2)二次探測法:di=12,-12,22,-22,…,k2,-k2 ( k<=m/2 )
- 沖突發生時,以原哈希地址為中心,在表的左右進行跳躍式探測,比較靈活。
- 3)偽隨機數法:di=偽隨機數序列。
- 具體實現時,應建立一個偽隨機數發生器,(如i=(i+p) % m),並給定一個隨機數做起點。
- 線性探測再散列的優點是:只要哈希表不滿,就一定能找到一個不沖突的哈希地址,而二次探測再散列和偽隨機探測再散列則不一定。
- 注:在開放定址的情形下,不能隨便物理刪除表中已有元素,若刪除元素將會截斷其他具有相同散列地址的元素的查找地址。若想刪除一個元素,給它做一個刪除標記,進行邏輯刪除。
- 2.鏈地址法、拉鏈法(開哈希表)
- 將所有哈希地址為i的元素構成一個稱為同義詞鏈的單鏈表,並將單鏈表的頭指針存在哈希表的第i個單元中,因而查找、插入和刪除主要在同義詞鏈中進行。鏈地址法適用於經常進行插入和刪除的情況。
- 3.再哈希法:同時構造多個不同的哈希函數,發生沖突時,使用其他哈希函數求值。這種方法不易產生聚集,但增加了計算時間。
- 4.建立公共溢出區:將哈希表分為基本表和溢出表兩部分,凡是和基本表發生沖突的元素,一律填入溢出表
- 1.開放定址法(閉哈希表):在沖突的哈希地址的基礎上進行處理,得到新的地址值。Hi = (H(key)+di) % m(m表示散列表表長,di為增量序列)
概述
-
哈希法又稱散列法、雜湊法以及關鍵字地址計算法等,相應的表稱為哈希表。這種方法的基本思想是:首先在元素的關鍵字k和元素的存儲位置p之間建立一個對應關系f,使得p=f(k),f稱為哈希函數。創建哈希表時,把關鍵字為k的元素直接存入地址為f(k)的單元;以后當查找關鍵字為k的元素時,再利用哈希函數計算出該元素的存儲位置p=f(k),從而達到按關鍵字直接存取元素的目的。
-
當關鍵字集合很大時,關鍵字值不同的元素可能會映象到哈希表的同一地址上,即 k1≠k2 ,但 H(k1)=H(k2),這種現象稱為沖突,此時稱k1和k2為同義詞。實際中,沖突是不可避免的,只能通過改進哈希函數的性能來減少沖突。
-
綜上所述,哈希法主要包括以下兩方面的內容:
1)如何構造哈希函數
2)如何處理沖突。
哈希函數的構造方法
-
構造哈希函數的原則是:①函數本身便於計算;②計算出來的地址分布均勻,即對任一關鍵字k,f(k) 對應不同地址的概率相等,目的是盡可能減少沖突。
-
下面介紹構造哈希函數常用的五種方法。
1. 數字分析法
- 如果事先知道關鍵字集合,並且每個關鍵字的位數比哈希表的地址碼位數多時,可以從關鍵字中選出分布較均勻的若干位,構成哈希地址。例如,有80個記錄,關鍵字為8位十進制整數d1d2d3…d7d8,如哈希表長取100,則哈希表的地址空間為:00~99。假設經過分析,各關鍵字中 d4和d7的取值分布較均勻,則哈希函數為:h(key)=h(d1d2d3…d7d8)=d4d7。例如,h(81346532)=43,h(81301367)=06。相反,假設經過分析,各關鍵字中 d1和d8的取值分布極不均勻, d1 都等於5,d8 都等於2,此時,如果哈希函數為:h(key)=h(d1d2d3…d7d8)=d1d8,則所有關鍵字的地址碼都是52,顯然不可取。
2. 平方取中法
-
當無法確定關鍵字中哪幾位分布較均勻時,可以先求出關鍵字的平方值,然后按需要取平方值的中間幾位作為哈希地址。這是因為:平方后中間幾位和關鍵字中每一位都相關,故不同關鍵字會以較高的概率產生不同的哈希地址。
-
例:我們把英文字母在字母表中的位置序號作為該英文字母的內部編碼。例如K的內部編碼為11,E的內部編碼為05,Y的內部編碼為25,A的內部編碼為01, B的內部編碼為02。由此組成關鍵字“KEYA”的內部代碼為11052501,同理我們可以得到關鍵字“KYAB”、“AKEY”、“BKEY”的內部編碼。之后對關鍵字進行平方運算后,取出第7到第9位作為該關鍵字哈希地址,如圖。
3. 分段疊加法
- 這種方法是按哈希表地址位數將關鍵字分成位數相等的幾部分(最后一部分可以較短),然后將這幾部分相加,舍棄最高進位后的結果就是該關鍵字的哈希地址。具體方法有折疊法與移位法。移位法是將分割后的每部分低位對齊相加,折疊法是從一端向另一端沿分割界來回折疊(奇數段為正序,偶數段為倒序),然后將各段相加。例如:key=12360324711202065,哈希表長度為1000,則應把關鍵字分成3位一段,在此舍去最低的兩位65,分別進行移位疊加和折疊疊加,求得哈希地址為105和907。
4. 除留余數法
-
假設哈希表長為m,p為小於等於m的最大素數,則哈希函數為
-
h(k)=k % p ,其中%為模p取余運算。
-
例如,已知待散列元素為(18,75,60,43,54,90,46),表長m=10,p=7,則有
h(18)=18 % 7=4 h(75)=75 % 7=5 h(60)=60 % 7=4
h(43)=43 % 7=1 h(54)=54 % 7=5 h(90)=90 % 7=6
h(46)=46 % 7=4
-
此時沖突較多。為減少沖突,可取較大的m值和p值,如m=p=13,結果如下:
h(18)=18 % 13=5 h(75)=75 % 13=10 h(60)=60 % 13=8
h(43)=43 % 13=4 h(54)=54 % 13=2 h(90)=90 % 13=12
h(46)=46 % 13=7
-
此時沒有沖突,如圖。
5. 偽隨機數法
-
采用一個偽隨機函數做哈希函數,即h(key)=random(key)。
-
在實際應用中,應根據具體情況,靈活采用不同的方法,並用實際數據測試它的性能,以便做出正確判定。通常應考慮以下五個因素 :
l 計算哈希函數所需時間 (簡單)。
l 關鍵字的長度。
l 哈希表大小。
l 關鍵字分布情況。
l 記錄查找頻率
處理沖突的方法
- 通過構造性能良好的哈希函數,可以減少沖突,但一般不可能完全避免沖突,因此解決沖突是哈希法的另一個關鍵問題。創建哈希表和查找哈希表都會遇到沖突,兩種情況下解決沖突的方法應該一致。下面以創建哈希表為例,說明解決沖突的方法。常用的解決沖突方法有以下四種:
1. 開放定址法
-
這種方法也稱再散列法,其基本思想是:當關鍵字key的哈希地址p=H(key)出現沖突時,以p為基礎,產生另一個哈希地址p1,如果p1仍然沖突,再以p為基礎,產生另一個哈希地址p2,…,直到找出一個不沖突的哈希地址pi ,將相應元素存入其中。這種方法有一個通用的再散列函數形式:
Hi=(H(key)+di)% m i=1,2,…,n
-
其中H(key)為哈希函數,m 為表長,di稱為增量序列。增量序列的取值方式不同,相應的再散列方式也不同。主要有以下三種:
l 線性探測再散列
dii=1,2,3,…,m-1
這種方法的特點是:沖突發生時,順序查看表中下一單元,直到找出一個空單元或查遍全表。
l 二次探測再散列
di=12,-12,22,-22,…,k2,-k2 ( k<=m/2 )
這種方法的特點是:沖突發生時,在表的左右進行跳躍式探測,比較靈活。
l 偽隨機探測再散列
di=偽隨機數序列。
具體實現時,應建立一個偽隨機數發生器,(如i=(i+p) % m),並給定一個隨機數做起點。
例如,已知哈希表長度m=11,哈希函數為:H(key)= key % 11,則H(47)=3,H(26)=4,H(60)=5,假設下一個關鍵字為69,則H(69)=3,與47沖突。如果用線性探測再散列處理沖突,下一個哈希地址為H1=(3 + 1)% 11 = 4,仍然沖突,再找下一個哈希地址為H2=(3 + 2)% 11 = 5,還是沖突,繼續找下一個哈希地址為H3=(3 + 3)% 11 = 6,此時不再沖突,將69填入5號單元,參圖8.26 (a)。如果用二次探測再散列處理沖突,下一個哈希地址為H1=(3 + 12)% 11 = 4,仍然沖突,再找下一個哈希地址為H2=(3 - 12)% 11 = 2,此時不再沖突,將69填入2號單元,參圖8.26 (b)。如果用偽隨機探測再散列處理沖突,且偽隨機數序列為:2,5,9,……..,則下一個哈希地址為H1=(3 + 2)% 11 = 5,仍然沖突,再找下一個哈希地址為H2=(3 + 5)% 11 = 8,此時不再沖突,將69填入8號單元,參圖8.26 (c)。
從上述例子可以看出,線性探測再散列容易產生“二次聚集”,即在處理同義詞的沖突時又導致非同義詞的沖突。例如,當表中i, i+1 ,i+2三個單元已滿時,下一個哈希地址為i, 或i+1 ,或i+2,或i+3的元素,都將填入i+3這同一個單元,而這四個元素並非同義詞。線性探測再散列的優點是:只要哈希表不滿,就一定能找到一個不沖突的哈希地址,而二次探測再散列和偽隨機探測再散列則不一定。
2. 再哈希法
-
這種方法是同時構造多個不同的哈希函數:
Hi=RH1(key) i=1,2,…,k
-
當哈希地址Hi=RH1(key)發生沖突時,再計算Hi=RH2(key)……,直到沖突不再產生。這種方法不易產生聚集,但增加了計算時間。
3. 鏈地址法
-
這種方法的基本思想是將所有哈希地址為i的元素構成一個稱為同義詞鏈的單鏈表,並將單鏈表的頭指針存在哈希表的第i個單元中,因而查找、插入和刪除主要在同義詞鏈中進行。鏈地址法適用於經常進行插入和刪除的情況。
-
例如,已知一組關鍵字(32,40,36,53,16,46,71,27,42,24,49,64),哈希表長度為13,哈希函數為:H(key)= key % 13,則用鏈地址法處理沖突的結果如圖8.27所示:
-
本例的平均查找長度 ASL=(17+24+3*1)=1.5
4、建立公共溢出區
- 這種方法的基本思想是:將哈希表分為基本表和溢出表兩部分,凡是和基本表發生沖突的元素,一律填入溢出表