雜湊表知識點小結

曾聰聰發表於2019-07-17

Set集合底層是基於HashMap的,再準備看Map原始碼集合前得有雜湊表和紅黑樹相關的資料結構的知識。

對雜湊表進行了溫習,對知識點做出以下小結

 

1.為什麼需要雜湊表?Hash函式是幹什麼用的?

2. 雜湊碰撞是什麼?雜湊碰撞的解決方法有哪些?

3.雜湊表的優缺點是什麼?

 

1.為什麼需要雜湊表?雜湊表是什麼?Hash函式是幹什麼用的?

無論是陣列還是連結串列都對查詢顯得有些無力,要想知道某個元素是否在其中只有從頭到尾進行對比查詢,效率較低。出現這個問題的根源就是我們沒辦法直接根據一個元素找到它的儲存位置。雜湊表便應運而生了。

 

雜湊表(雜湊表):是通過關鍵碼值(Key)進行訪問的一種資料結構。Key通過特定的雜湊函式進行計算對映成一個int數值得到。

 

雜湊函式就是用來計算得到特定的int型數值的規則,如資料結構所學到的除留餘數法,直接定址法等

 

2.解決hash碰撞的方法有哪些?

我們知道int的值是有限的,它只有2^32^個,通過雜湊函式計算後的所得到的int數值會有重複,此時會產生衝突,即雜湊碰撞。解決方法有許多,如二維陣列法,開放定址法,陣列+連結串列法等

 

開放地址法:雜湊表基本不會像陣列一樣每個位置都有元素,這樣就可以將碰撞的元素插入到這些空閒的位置中區,這種方案稱為定址法。有一次線性探測,二次線性探測,這都是資料結構考過的內容,但其可擴充套件性不佳,且JDK原始碼中也不是使用這種方法解決

 

二維陣列法:即將碰撞的元素按照順序依次儲存起來,但最大的缺點是陣列的大小是固定的,所以第二維的陣列長度都是一樣的,但是雜湊碰撞一定是比較少發生的情況,也就是我們宣告瞭一個很大的陣列,但是其中大部分都是閒置的,這就浪費了大量的記憶體。如下圖所示

 

拉鍊法:目前比較通用的一種方式,陣列+連結串列組合的方式。這是當前比較理想的方法,既繼承了陣列的優點,又在碰撞時繼承了連結串列的優點,這也是雜湊表強大的地方之一。當出現雜湊碰撞時,在該位置的資料就通過連結串列的方式連結起來,如下圖所示:

在JDK1.7及之前的版本中,HashMap的儲存結構和上圖是一致的,在JDK1.8之後還加入了紅黑樹以進一步優化,之後將對樹,二叉樹,紅黑樹進行整理。

2.雜湊碰撞的優缺點

雜湊表是一種優化儲存的思想,具體儲存元素的依然是其他的資料結構。設計良好的雜湊表,能同時兼備陣列和連結串列的優點,它能在插入和查詢時都具備良好的效能。然而設計不好的雜湊表,有可能會出現較多的雜湊碰撞,導致連結串列過長,從而雜湊表會更像一個連結串列。還有當資料量很大時,為防止連結串列過長,就需要對陣列進行擴容,這時就涉及到了陣列的拷貝,其對效能的影響也很嚴重,所以需要提前對可能的情況有良好的預測,才能真正發揮雜湊表的優勢。

PS:以上皆為純理論的知識點,具體的實現程式碼需要結合搜尋引擎加以練習。後面兩天會去做這方面練習。

 

相關文章