基本概念
哈希表(hash table):又稱散列表,其基本思路是,設要存儲的元素個數是n,設置一個長度為m的連續存儲單元,以每個元素的關鍵字作為自變量,通過哈希函數(h(k))把k映射到一個內存單元,並把該元素存在這個內存單元中,把像這樣構造的線性表存儲結構稱為哈希表。
哈希沖突(hash collisions):在構建哈希表時,出現兩個不同關鍵詞對應相同的哈希值,這種現象稱作哈希沖突。
裝填因子(loading factor):設哈希表空間大小為n,填入表中元素個數為m,則$α=/frac{m}{n}$為哈希表的裝填因子。
哈希查找兩項基本工作:
- 計算位置:構造哈希函數確定關鍵詞的位置
- 解決沖突:應用某種策略解決多個關鍵詞位置相同的問題
這種查找的時間復雜度幾乎是常量O(1),即查找時間與問題規模無關。
哈希函數的構造
一個好的哈希函數:
- 計算簡單,以便提高轉換速度
- 關鍵詞對應地空間分布均勻,以盡量減少沖突
直接定址法
是以關鍵字k加上某個常量c作為哈希地址的方法,其哈希函數為:h(k)=k+c
特點:哈希函數計算簡單。當關鍵字分布基本連續時,可以用直接定址法;否則,將造成內存單元大量浪費
除留余數法
是用關鍵字k除以整數p所得的余數作為哈希地址,表示為h(k)=k mod p
特點:計算比較簡單,適用范圍廣,是最經常使用的一種哈希函數。
這種方法的關鍵是選好p,使得每個關鍵字經轉換后映射到哈希表任意地址的概率相等。理論表明,p取不大於表長的素數時效果最好
數字分析法
是指提取關鍵字中取值較均勻的數字作為哈希地址
特點:它適用於所有關鍵字已知的情況,需要對關鍵字每一位的取值分布情況加以分析。
其它構造整數關鍵字的哈希函數還有平方取中法、折疊法、隨機數法等。
哈希沖突的解決方法
開放定址法
線性探測法
是指從發生沖突的地方開始,依次探測下一個地址(表尾的下一個地址是表頭),直到找到一個空閑的單元為止。
表示為:d0=h(k) di=((di-1+1)) mod size
特點:操作簡單。但有一個重大的缺陷是容易產生聚集現象,當一個發生沖突,后面緊接着的單元都會由於前面的堆積發生沖突。
平方探測法
是指發生沖突時以±i2 進行探測,公式為:d0=h(k) di=((d0 ± i2)) mod size
特點:是一種較好的處理沖突的方法,其缺點是不一定能探測到哈希表上的所有單元,但至少能探測到一半單元。
理論表明,哈希表的長度為4k+3(k為整數)形式的素數,平方探測法可以探測到整個哈希表空間。
其它方法還有偽隨機序列法、雙哈希函數法等
拉鏈法
是指將所有哈希值相同的關鍵字用單鏈表鏈接起來。
在這種方法中,哈希表的每個單元存放的不再是元素本身,而是一個個單鏈表的頭結點。
與開放定址法比較:
- 處理沖突簡單,無堆積現象,因此平均查找長度較短
- 由於單鏈表的結點是動態申請,適合元素規模未知的情況
- 開放地址法為了減少沖突要求裝填因子較小,故當數據規模較大時浪費空間;拉鏈法節省空間
- 用拉鏈法構造的哈希表中,刪除結點比較簡單
哈希表的性能分析
用平均查找長度(ASL)來度量查找表的查找效率:成功、不成功
哈希表的性能就是看比較次數,而比較次數取決於沖突的多少,影響沖突的因素:
- 哈希函數是否均勻
- 處理沖突的方法
- 裝填因子α
我們這里只考慮后兩種因素,主要是一些理論上的結果
線性探測法
可以證明,線性探測法的期望探測次數為:
當α=0.5時,ASLu=2.5次,ASLs=1.5次。
平方探測法
可以證明,平方探測法的期望探測次數為:
當α=0.5時,ASLu=2次,ASLs=1.39次
拉鏈法
把所有單鏈表的平均長度定義成裝填因子α,α有可能超過1,可以證明,其平均期望探測次數p為:
當α=1時,ASLu=1.37次,ASLs=1.5次
總結
- 選取合適的哈希函數h(key),查找效率的期望是O(1)
- 以較小的α為前提,實質是以空間換時間
- 哈希表對關鍵詞是隨機存儲的,不便順序查找
- 不適合范圍查找、最大最小值查找
參考鏈接:中國大學mooc 陳越、何欽銘 數據結構