數據結構——hash函數、散列表

散列表(hash表):是根據關鍵碼值而直接進行訪問的數據結構java

在記錄的存儲位置和它的關鍵字之間創建一個肯定的對應關係f,使每個關鍵字和結構中惟一的存儲位置相對應。稱這個對應關係f爲哈希(hash)函數,按這個思想創建的表爲哈希表若關鍵字爲k,則其值存放在f(k)的存儲位置上。數組

對不一樣的關鍵字可能獲得同一散列地址,即k1≠k2,而f(k1)=f(k2),這種現象稱爲衝突。具備相同函數值的關鍵字對於該哈希函數來講稱做同義詞。(此處,k1,k2互爲同義詞)數據結構

根據散列函數f(k)處理衝突的方法將一組關鍵字映射到一個有限的連續的地址集(區間)上,並以關鍵字k在地址集中的「像」f(k)做爲記錄在表中的存儲位置,這種表便稱爲散列表,所得的存儲位置稱散列地址函數

實際工做中需視不一樣的狀況採用不一樣的哈希函數和不一樣的處理碰撞衝突的方法。spa

經常使用的hash函數:

  • 直接地址法
  • 數字分析法
  • 平方取中法
  • 摺疊法
  • 除留餘數法(H\left ( key \right )=key MOD\displaystyle p,p\leq M,選p爲素數或小於20的質因數的和數,eg:3,5,7,15,23.....)
  • 隨機法

散列函數和鍵的類型有關,eg:若是鍵是一個數字, 咱們能夠直接使用這個數字;若是鍵是一個字符串,就須要將這個字符串轉化爲一個數字;若是鍵包含多個部分(好比email地址),就須要某種方法將這些部分結合起來。 code

構造hash函數 須要考慮的因素有:

  • 計算hash函數所需時間;
  • 關鍵字的長度;
  • hash表的大小;
  • 關鍵字的分佈狀況;
  • 記錄的查找頻率。

對於長度爲M的表,必須知足\forall k,f(k)\sqsubseteq (0,M-1),即任何關鍵字所得的存儲位置必須落在表長容許範圍內。blog

經常使用處理衝突的方法:

  • 開放地址法(依靠數組中的空位解決碰撞衝突,要求數組長度M〉鍵值對個數N)
  • 再哈希法
  • 鏈地址法 (將全部關鍵字爲同義詞的記錄存儲在同一線性鏈表中)。最經常使用
  •  創建一個公共溢出區

 圖中,紫色部分即表明哈希表,也稱爲哈希數組,數組的每一個元素都是一個單鏈表的頭節點,鏈表是用來解決衝突的,若是不一樣的key映射到了數組的同一位置處,就將其放入單鏈表中。字符串

 

  java中的HashMap的底層主要就是基於數組和鏈表來實現的,HashMap底層是經過鏈表來解決hash衝突的。get