哈希表(hash table)

前言:

當我們學習了數組和鏈表後,我們會發現數組的特點是:尋址容易,插入和刪除困難;而鏈表的特點是:尋址困難,插入和刪除容易。比如我們要找尋一個key對應的value,若用鏈表,時間複雜度爲O(n),即使採用二叉排序樹進行存儲,也最多爲O(logn)。但哈希表就能很好的將數組與鏈表的優點結合,從而達到查找的時間複雜度達到O(1),你不信???不信就來看看這種數據結構的強大之處。

哈希表:

Hash表就是採用了一個映射函數 f :key —> address 將key映射到該記錄在表中的存儲位置,從而在存儲時,可以直接根據關鍵字和映射關係計算出該記錄在表中的存儲位置,然後在這個位置放入value,而在想要查找該記錄時,可以直接根據關鍵字和映射關係計算出該記錄在表中的存儲位置,然後輸出value。通常情況下,這種映射關係稱作爲Hash函數,而通過Hash函數和關鍵字計算出來的存儲位置(注意這裏的存儲位置只是表中的存儲位置,並不是實際的物理地址)稱作爲Hash地址。

hash函數:

1 直接定址法

取key的某個線性函數爲Hash地址,即address(key)=a * key + b。如知道學生的學號從2000開始,最大爲4000,則可以將address(key)=key-2000作爲Hash地址。

2 平方取中法

對關鍵字進行平方運算,然後取結果的中間幾位作爲Hash地址。假如有以下關鍵字序列{421,423,436},平方之後的結果爲{177241,178929,190096},那麼可以取中間的兩位數{72,89,00}作爲Hash地址。

3 摺疊法

將關鍵字拆分成幾部分,然後將這幾部分組合在一起,以特定的方式進行轉化形成Hash地址。假如知道圖書的ISBN號爲8903-241-23,可以將address(key)=89+03+24+12+3作爲Hash地址。

4 除留取餘法

如果知道Hash表的最大長度爲m,可以取不大於m的最大質數p,然後對關鍵字進行取餘運算,address(key)= key % p。

在這裏p的選取非常關鍵,p選擇的好的話,能夠最大程度地減少衝突,p一般取不大於m的最大質數。

5 斐波那契法

平方散列法的缺點是顯而易見的,所以我們能不能找出一個理想的乘數,而不是拿value本身當作乘數呢?答案是肯定的。

1,對於16位整數而言,這個乘數是40503 
2,對於32位整數而言,這個乘數是2654435769 
3,對於64位整數而言,這個乘數是11400714819323198485

    這幾個“理想乘數”是如何得出來的呢?這跟斐波那契數列有關。0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946,…。   

對我們常見的32位整數而言,公式: 
            index = (key * 2654435769) >> 28

上面講了幾種hash函數的操作,那麼當數據很多時,不免會出現address重複的情況,下面來看看hash解決衝突的方法:

1 開放定址法

       當一個關鍵字和另一個關鍵字發生衝突時,使用某種探測技術在Hash表中形成一個探測序列,然後沿着這個探測序列依次查找下去,當碰到一個空的單元時,則插入其中。比較常用的探測方法有線性探測法,比如有一組關鍵字{12,13,25,23,38,34,6,84,91},Hash表長爲14,Hash函數爲address(key)=key%11,當插入12,13,25時可以直接插入,而當插入23時,地址1被佔用了,因此沿着地址1依次往下探測(探測步長可以根據情況而定),直到探測到地址4,發現爲空,則將23插入其中。

2 鏈地址法

     採用數組和鏈表相結合的辦法,將Hash地址相同的記錄存儲在一張線性表中,而每張表的表頭的序號即爲計算得到的Hash地址。如上述例子中,採用鏈地址法形成的Hash表存儲表示爲:

雖然能夠採用一些辦法去減少衝突,但是衝突是無法完全避免的。因此需要根據實際情況選取解決衝突的辦法。

總結:

Hash表是一種特殊的數據結構,它同數組、鏈表以及二叉排序樹等相比較有很明顯的區別,它能夠快速定位到想要查找的記錄,而不是與表中存在的記錄的關鍵字進行比較來進行查找。這個源於Hash表設計的特殊性,它採用了函數映射的思想將記錄的存儲位置與記錄的關鍵字關聯起來,從而能夠很快速地進行查找。但hash表也有不足:它是基於數組的,數組創建後難於擴展,某些哈希表被基本填滿時,性能下降得非常嚴重,所以程序員必須要清楚表中將要存儲多少數據,或者準備好定期地把數據轉移到更大的哈希表中,這是個費時的過程。

 

 

最後強烈推薦Coursera上普林斯頓大學的算法課點擊打開鏈接

 

 

以上內容純屬個人學習總結,不代表任何團體或單位。若有理解不到之處請見諒!

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章