圖解哈希表及其原理

要點回顧

此部分方便知識點快速回顧,首次閱讀請從引言部分開始。數組

  • 哈希表(Hash Table)其實也叫散列表,是一個數據結構。數據結構

  • 哈希表本質上就是一個數組,只不過數組存放的是單一的數據,而哈希表中存放的是鍵值對(key - value pair)。函數

  • key 經過哈希函數(hash function)獲得數組的索引,進而存取索引位置的值。優化

  • 不一樣的 key 經過哈希函數可能獲得相同的索引值,此時,產生了哈希碰撞。blog

  • 經過在數組中插入鏈表或者二叉樹,能夠解決哈希碰撞問題。排序

引言

哈希這個詞想必你們常常聽到,這也說明了它使用的頻繁程度,HashMap 和 HashTable 都與哈希這個詞有關係。那哈希是什麼,要搞清楚它,咱們得先來講下哈希表。索引

什麼是哈希表?

哈希表(Hash Table) 是一種用於存儲 鍵值對 的基本數據結構。在 C++ 中,哈希表使用 哈希函數 來計算數組的索引,進而存取數組中對應索引位置的值。內存

百科定義:get

散列表(Hash table,也叫哈希表),是根據鍵(Key)而直接訪問在內存存儲位置的數據結構。也就是說,它經過計算一個關於鍵值的函數,將所需查詢的數據映射到表中一個位置來訪問記錄,這加快了查找速度。這個映射函數稱作散列函數,存放記錄的數組稱作散列表。hash

計算索引的過程被稱爲 哈希(hash)

哈希表實現原理

用一個簡單的例子來講明哈希表的原理:

假設:有一本中文詞典,裏面包含了全部的漢字,可是這些漢字是按任意順序隨意排版的,那麼想要在其中找到某一個漢字,你就須要從頭到尾一個一個核查,若是運氣差,這個漢字正好在詞典的末尾,那你須要遍歷整本詞典才能找到你要查的漢字。

優化:由於漢字和拼音之間存在着一種肯定的關係,爲了提升查找速度,如今將全部漢字按照拼音(key)進行排序(拼音能夠根據首字母,第二個字母依次進一步排序),而且每一個拼音都有一個對應頁碼(index),從該頁開始,存放拼音對應的漢字(value)。因此找到拼音,也就能在對應的頁碼找到對應的漢字。其中,拼音和頁碼之間,有着某種固定的映射關係,能夠經過某種方式計算出來(hash function)。

因而可知,哈希表能夠根據一個 key 值來直接訪問數據,所以查找速度快。

可是,上面的例子,還存在一個問題,放在同一頁碼(具備相同拼音)的漢字可能不止一個(同音字),這時候經過拼音(key)獲取到的漢字(value)應該是哪一個呢?這就出現了碰撞(hash collision)

爲了解決碰撞,實現哈希表能夠有如下兩種方式:

  • 數組 + 鏈表
  • 數組 + 二叉樹

因此,哈希表本質上就是一個數組。只不過數組存放的是單一的數據,而哈希表中存放的是鍵值對。

鏈表或二叉樹是用來解決碰撞的。

下面用圖例說明哈希表以及解決哈希碰撞的鏈表實現:

由於哈希表中 key 必須是惟一的,因此圖示給拼音加了後綴 _1 和 _2。key han_1han_2 經過哈希函數 F(x) 計算出來的頁碼都是 244。這時就產生了哈希碰撞。爲了解決碰撞問題,新建了一個鏈表,鏈表的每一個結點都包含了一個鍵值對,當輸入 key han_2 時,哈希表在 244 位置找到了鍵值對 [han_1 - 漢],可是經過比對發現找到的鍵值對的 key 是 han_1,不等於 han_2,因此繼續遍歷到鏈表的下一個結點,下一個結點存放了鍵值對 [han_2 - 汗],經過比較發現 key 確實是 han_2,所以返回了漢字(value)

引用

https://www.educba.com/c-plus-plus-hash-table/

https://mp.weixin.qq.com/s/AkPIN6Ugno9vkQ2AAmCEAA

相關文章
相關標籤/搜索