一、哈希表
1、概念
哈希表(Hash Table)也叫散列表,是依據關鍵碼值(Key Value)而直接進行訪問的數據結構。它通過把關鍵碼值映射到哈希表中的一個位置來訪問記錄,以加快查找的速度。
這個映射函數就做散列函數。存放記錄的數組叫做散列表。
2、散列存儲的基本思路
以數據中每一個元素的keywordK為自變量。通過散列函數H(k)計算出函數值,以該函數值作為一塊連續存儲空間的的單元地址,將該元素存儲到函數值相應的單元中。
3、哈希表查找的時間復雜度
哈希表存儲的是鍵值對,其查找的時間復雜度與元素數量多少無關。哈希表在查找元素時是通過計算哈希碼值來定位元素的位置從而直接訪問元素的,因此,哈希表查找的時間復雜度為O(1)。
二、經常使用的哈希函數
1. 直接尋址法
取keyword或者keyword的某個線性函數值作為哈希地址,即H(Key)=Key或者H(Key)=a*Key+b(a,b為整數),這樣的散列函數也叫做自身函數.假設H(Key)的哈希地址上已經有值了,那么就往下一個位置找,知道找到H(Key)的位置沒有值了就把元素放進去.
2. 數字分析法
分析一組數據,比方一組員工的出生年月,這時我們發現出生年月的前幾位數字一般都同樣,因此,出現沖突的概率就會非常大,可是我們發現年月日的后幾位表示月份和詳細日期的數字區別非常大,假設利用后面的幾位數字來構造散列地址,則沖突的幾率則會明顯減少.因此數字分析法就是找出數字的規律,盡可能利用這些數據來構造沖突幾率較低的散列地址.
3. 平方取中法
取keyword平方后的中間幾位作為散列地址.一個數的平方值的中間幾位和數的每一位都有關。
因此,有平方取中法得到的哈希地址同keyword的每一位都有關。是的哈希地址具有較好的分散性。
該方法適用於keyword中的每一位取值都不夠分散或者較分散的位數小於哈希地址所須要的位數的情況。
4. 折疊法
折疊法即將keyword切割成位數同樣的幾部分,最后一部分位數能夠不同,然后取這幾部分的疊加和(注意:疊加和時去除進位)作為散列地址.數位疊加能夠有移位疊加和間界疊加兩種方法.移位疊加是將切割后的每一部分的最低位對齊,然后相加;間界疊加是從一端向還有一端沿切割界來回折疊,然后對齊相加.
5. 隨機數法
選擇一個隨機數,去keyword的隨機值作為散列地址,通經常使用於keyword長度不同的場合.
6. 除留余數法
取keyword被某個不大於散列表表長m的數p除后所得的余數為散列地址.即H(Key)=Key MOD p,p<=m.不僅能夠對keyword直接取模,也可在折疊、平方取中等運算之后取模。對p的選擇非常重要,一般取素數或m,若p選得不好。則非常easy產生沖突。
一般p取值為表的長度tableSize。
三、哈希沖突的處理方法
1、開放定址法——線性探測
線性探測法的地址增量di = 1, 2, ... , m-1,當中,i為探測次數。該方法一次探測下一個地址。知道有空的地址后插入。若整個空間都找不到空余的地址,則產生溢出。

線性探測easy產生“聚集”現象。當表中的第i、i+1、i+2的位置上已經存儲某些keyword,則下一次哈希地址為i、i+1、i+2、i+3的keyword都將企圖填入到i+3的位置上,這樣的多個哈希地址不同的keyword爭奪同一個后繼哈希地址的現象稱為“聚集”。聚集對查找效率有非常大影響。
2、開放地址法——二次探測
二次探測法的地址增量序列為 di = 12, -12, 22。 -22,… 。 q2, -q2 (q <= m/2)。二次探測能有效避免“聚集”現象,可是不可以探測到哈希表上全部的存儲單元,可是至少可以探測到一半。
3、鏈地址法
鏈地址法也成為拉鏈法。
其基本思路是:將全部具有同樣哈希地址的而不同keyword的數據元素連接到同一個單鏈表中。假設選定的哈希表長度為m,則可將哈希表定義為一個有m個頭指針組成的指針數組T[0..m-1]。凡是哈希地址為i的數據元素,均以節點的形式插入到T[i]為頭指針的單鏈表中。而且新的元素插入到鏈表的前端,這不僅由於方便。還由於常常發生這種事實:新近插入的元素最優可能不久又被訪問。
鏈地址法特點
(1)拉鏈法處理沖突簡單。且無堆積現象,即非同義詞決不會發生沖突,因此平均查找長度較短;
(2)因為拉鏈法中各鏈表上的結點空間是動態申請的。故它更適合於造表前無法確定表長的情況。
(3)開放定址法為降低沖突。要求裝填因子α較小。故當結點規模較大時會浪費非常多空間。而拉鏈法中可取α≥1,且結點較大時,拉鏈法中添加的指針域可忽略不計,因此節省空間;
(4)在用拉鏈法構造的散列表中,刪除結點的操作易於實現。僅僅要簡單地刪去鏈表上對應的結點就可以。而對開放地址法構造的散列表,刪除結點不能簡單地將被刪結點的空間置為空,否則將截斷在它之后填人散列表的同義詞結點的查找路徑。這是由於各種開放地址法中,空地址單元(即開放地址)都是查找失敗的條件。
因此在用開放地址法處理沖突的散列表上運行刪除操作。僅僅能在被刪結點上做刪除標記,而不能真正刪除結點。

四、哈希表的裝填因子
裝填因子 = (哈希表中的記錄數) / (哈希表的長度)
裝填因子是哈希表裝滿程度的標記因子。值越大。填入表中的數據元素越多,產生沖突的可能性越大。
五、不同處理沖突的平均查找長度

例:
如果散列表的長度是13,三列函數為H(K) = k % 13,給定的keyword序列為{32。 14, 23, 01。 42, 20。 45, 27, 55。 24。 10。 53}。分別畫出用線性探測法和拉鏈法解決沖突時構造的哈希表,並求出在等概率情況下,這兩種方法的查找成功和查找不成功的平均查找長度。
(1)線性探測法:

ASL = (1+2+1+4+3+1+1+3+9+1+1+3)/12 = 2.5
查找成功時的查找次數:第n個位置不成功時的比較次數為,第n個位置到第1個沒有數據位置的距離:如第0個位置取值為1,第1個位置取值為2.
查找不成功的平均查找次數為:
ASL = (1+2+3+4+5+6+7+8+9+10+11+12)/ 13 = 91/13
(2)鏈地址法

查找成功時的平均查找長度:
ASL = (1*6+2*4+3*1+4*1)/12 = 7/4
查找不成功時的平均查找長度:
ASL = (4+2+2+1+2+1)/13
注意:查找成功時。分母為哈希表元素個數,查找不成功時,分母為哈希表長度。
