哈希表的概念
哈希表(Hash Table)也叫散列表,是根據鍵碼值(key value)而直接進行訪問的數據結構。它通過把關鍵碼值映射到哈希表中的一個位置來訪問記錄,以加快查找速度。這個映射函數就叫做散列函數,存放記錄的數組的散列表。
哈希表查找的時間複雜度
哈希表存儲的是鍵值對,其查找的時間複雜度與元素數量的多少無關,哈希表在查找元素的時候通過計算哈希碼值來定位元素的位置從而直接訪問元素的,因此哈希表查找的時間複雜度爲O(1)。
當向哈希表
插入元素時:根據待插入元素的關鍵碼,計算出該元素的存儲位置,並進行存放。
查找元素時:對元素的關鍵碼進行同樣的計算,把求得的函數值當做元素的存儲位置,
在結構中,按此位置取元素比較,若關鍵碼相等,則搜索成功。
常見的哈希函數
直接定製法
取關鍵字的某個線性函數爲散列地址:Hash(Key)= A*Key + B
優點:簡單、均勻
缺點:需要事先知道關鍵字的分佈情況
適合查找比較小且連續的情況
面試題:找出一個字符串中第一個只出現一次的字符,要求:時間複雜度O(N),空間複雜度O(1)除留餘數法
設散列表中允許的地址數爲m,取一個不大於m,但最接近或者等於m的質數p作爲除數,按照哈希函數:Hash(key) = key % p(p<=m),將關鍵碼轉換成哈希地址
- 摺疊法
- 數學分析法
- 隨機數法
- 平方取中法
哈希衝突
即不同關鍵字通過相同哈希哈數計算出相同的哈希地址,該種現象稱爲哈希衝突或哈希碰撞。把具有不同關鍵碼而具有相同哈希地址的數據元素稱爲“同義詞”。
那麼我們如何解決哈希衝突呢?
常用的解決哈希衝突的方法有兩種:開散列法,閉散列法
閉散列
閉散列:也叫開放地址法,當發生哈希衝突時,如果哈希表未被裝滿,說明在哈希表中必然還有空位置,那麼可以把key存放到表中“下一個” 空位中去。
常用的探測方法有 :線性探測、二測談探測等。
負載因子:
散列表的負載因子定義爲:a = 填入表中的元素個數 / 散列表長度對於開放定址法,
散列荷載因子是重要的影響因素,應該嚴格限制在0.7~0.8,超過0.8,cpu緩衝不命
中按指數曲線上升。
開散列
開散列法又叫鏈地址法(開鏈法)。
開散列法:首先對關鍵碼集合用散列函數計算散列地址,具有相同地址的關鍵碼歸於同一子集合,每一個子集合稱爲一個桶,各個桶中的元素通過一個單鏈錶鏈接起來,各鏈表的頭結點存儲在哈希表中。
通常,每個桶對應的鏈表結點都很少,將n個關鍵碼通過某一個散列函數,存放到散列表中的m個桶中,那麼每一個桶中鏈表的平均長度爲 n / m 。以搜索平均長度爲 n / m 的鏈表代替了搜索長度爲 n 的順序表,搜索效率快的多。
接下來我們將實現一下開散列以及閉散列,具體代碼請參考我的另一篇博客:
哈希表具體實現