程序員常說的「哈希表」是個什么鬼?

6 評論 39516 瀏覽 53 收藏 6 分鐘

今天聊聊「哈希表」,「哈希表」主要作用在于高效查找。

在編程實現中,常常面臨著兩個問題:存儲和查找,存儲和查找的效率往往決定了整個程序的效率。

腦補下,你在家里忘記了指甲刀放在哪里,通常要在你家所有抽屜中順序尋找,直到找到,最差情況下,有N個抽屜,你就要打開N個抽屜。這種存儲方式叫數組,查找方法稱為「遍歷」。

腦補下,你是一個整理控,所有物品必須分門別類放入整理箱,再將整理箱編號,比如1號放入針線,2號放入證件,3號放入細軟。這種存儲和查找方式稱為「哈?!?,如果這個時候要查找護照,你不許要再翻所有抽屜,直接可在2號整理箱中獲取,通常只用一次查找即可,如何編號整理箱,稱為哈希算法。

同樣是查找,差距怎么那么大涅~,假設我們有100億條數據記錄,那差距就變得明顯,遍歷需要查找最多100億次,最少1次,哈希只需1次。

讓我們正式介紹哈希和哈希算法,哈希也稱散列,哈希表是一種與數組、鏈表等不同的數據結構,與他們需要不斷的遍歷比較來查找的辦法,哈希表設計了一個映射關系f(key)= address,根據key來計算存儲地址address,這樣可以1次查找,f既是存儲數據過程中用來指引數據存儲到什么位置的函數,也是將來查找這個位置的算法,叫做哈希算法。

讓我們舉個例子,比如下面這幾個人物,按數組存儲:


這樣我要找到大胸姐的電話號碼,需要順序查找對比整個數組,第一個余罪,不是,第二個不是,第三個不是,直到第四個找到大胸姐。

如果以hash存儲呢?首先讓我們來看看如何設計哈希算法,哈希算法可以隨意設計,教科書上一般會說以下幾種方法:直接定址發,平方取中法,除數取余法,哈希算法的本質上是計算一個數字,如果用這幾種方法講解會稍顯晦澀,我們假設我們的哈希算法是取姓名的首字母。所以f(余罪) = y, f(傅老大) = f,f(沈嘉文) = s,f(大胸姐) = d。

構建的hash表如下:

我們看到他們分別以姓名首字母的位置插入到這一張表格中,這樣我們構建了這樣一個Key-Value表格,此表就是哈希表,也稱為Hash Table。未來,當我們要查找余罪的時候,通過計算,余罪在y位置,可以通過1次查找,找到這條記錄,也即手機號。

這個時候有客官問了,那以首字母為哈希函數的話,應該有很多比如以y的姓名啊,這個時候就不是一次查找了吧,其實有很多條記錄都映射到一個位置上,稱為哈希沖突。

哈希沖突是跟哈希函數的設計正相關的,你的隨機性越大,那么產生哈希沖突的可能性越小,在小概率下,如果還有沖突怎么辦,這個時候要做些有損的設計,比如如果有兩個首字母為y的姓名,那么可以接到余罪的后面,當查找的時候,需要先查找到y,然后再順序查找,如圖所示:

還有一些解決哈希沖突的辦法叫「哈希再哈?!?,也就是針對第一次哈希的結果再進行一次hash來減小沖突的概率。

這就是Hash表,首先Ta是一種數據結構,是一種效率極高的查找方式,哈希表的核心在于哈希函數的設計,哈希沖突了不要緊,我們要增加隨機性以及對沖突進行適當的有損化的處理。

#專欄作家#

給產品經理講技術,微信公眾號(pm_teacher),人人都是產品經理專欄作家。資深程序猿,專注客戶端開發若干年,對前端、后臺技術略懂,熱衷于對新的科技領域的探索。

本文原創發布于人人都是產品經理。未經許可,禁止轉載。

題圖來自PEXELS,基于CC0協議

更多精彩內容,請關注人人都是產品經理微信公眾號或下載App
評論
評論請登錄
  1. 呵呵噠

    回復
  2. 以前上課的時候老師叨叨了半天不懂的,在你這里看了幾分鐘的文章就懂了,哎……

    來自四川 回復
  3. 我的天。。我們上數據結構的老師上來直接講哈希表是怎么做的,怎么做那種將一個數據和其哈希值(位置?)對應。根本沒講哈希算法是用來查找的。。

    來自江蘇 回復
    1. 你確定有在聽課。。。

      來自福建 回復
    2. ??

      來自江蘇 回復