1. 散列的概念
散列(Hash):既是一種存儲方式,又是一種查找方法。又稱作哈希查找。
散列表/哈希表:按散列存儲方式構造的查找表,稱之爲~。
散列基本思想:以關鍵碼爲自變量,通過一定的函數關係計算出函數值,將函數值作爲結點的存儲地址,將結點存入計算得到的存儲單元中。其函數則爲散列函數。
散列搜索算法:主要由兩部分組成:散列函數和衝突調節。
衝突調節:理想的情況是不同的關鍵字映射到同的地址,但經常會出現兩個或多個關鍵字映射到同一個地址,即衝突。處理這種關鍵字的過程即爲衝突調節。
例1-散列表:關鍵碼序列爲{2,5,8,6}存儲到編號爲0到4,表長爲5的數組中,計算存儲地址的散列函數採用模5的方法,即散列函數:H(key)=key%5 求散列表。
散列表計算過程:
2 % 5 =2 --> array[2] =2;
5 % 5 = 0 --> array[0] = 5;
8 % 5 = 3--> array[3] = 8;
6 % 5 = 1--> array[1] = 6;
即散列表的存儲序列爲 array[5]={5,6,2,8}
2.常用的散列函數
(1)直接地址法
H(key) = a * key + b (a,b 爲常數)
(2)除留餘法
H(key) = key % p
據理論分析和測試結果,p應取小於列表長度m的素數,或不包含小於20的質因數的合數。
(3)平方取中法
(4)數字分析法
(5)摺疊法
3.處理衝突的方法
(1)開放地址法
當衝突發生時,形成一個地址序列,沿關這個地址序列逐個探測,直到找到一個“空”的開放地址,將衝突發生的關鍵字存到該地址中去。
其序列稱爲探測序列;由此生成的散列表稱爲閉散列表。
A.線性探測再散列
當衝突發生時,順序查看錶中下一個位置,直到找到一個空的位置,將關鍵字存入這個地址。
Hi = ( H(key) + di ) %m (di=1,2,3…爲探測序列)
B.二次探測再散列
衝突發生時,在表的左右進行跳躍性控測。比較靈活。
Hi = ( H(key) + di ) %m
(di=1平方,-1平方,2平方,-2平方…q平方,-q平方,且q<=m/2)
(2)鏈地址法
把具有相同散列地址的關鍵碼存入同一個單鏈表中。散列表中的每個單元存儲的不是元素,而是相應單鏈表的頭指針。
優點:能較好的解決溢出問題;缺點:存儲空間增加,空閒存儲單元增加。
例2-衝突調節:關鍵碼集合爲{47,7,29,11,16,92,22,8,3},散列表表長爲11,散列函數爲
H(key) = key % 11.寫出分別使用線性探測再散列、二次探測再散列和鏈地址法的所得到的散列表。
(1)線性探性測再散列:Hi = ( H(key) + di ) % m
如當計算 3 % 11 = 3時,發生衝突,採用衝突處理:
((3 % 11)+ 1 )% 11 = 4, 衝突!再探測一下個,
((3 % 11)+ 2 )% 11 = 5, 衝突,再下一個,
((3 % 11)+ 3 )% 11 = 6, OK!
(2)二次探測再散列
如當計算 3 % 11 = 3 時,發生衝突, 採用衝突處理:
((3 % 11)+ 1 )% 11 = 4,再次衝突,探測下一個 ,
((3 % 11)- 1 )% 11 = 2, OK!
(3)鏈地址法
如計算3 % 11 = 3 ,將3插入到已存在的單鏈表中,插入到結點47的前面。
參考:《數據結構》.王玉.2008.山東出版社