數據結構(十二)散列表
阿新 • • 發佈:2017-07-14
問題 目的 hab 二分 編譯 com over 編譯器優化 nal
定義
以下簡稱hahs應用場景
適合查找與給定值相同的數據,不適合做範圍查找,1對多映射查找問題
沖突,散列表的理論依據是每個不同的關鍵字通過散列算法得到的結果都是唯一的,而現實中有可能出現幾個結果相同的關鍵字。hash算法
構造一個散列算法考慮幾個方面直接定址法
按如下公式計算出關鍵字的hash值,當原始的key不重復,則得到的hash值就不會沖突數字分析法
抽取關鍵字的一部分作為hash值 例如手機號,一般可以取後4位或者後4位的變形作為hash值,(公司內部場景)平方取中法
折疊法
除留余數法
隨機數法
java針對stirng的hash算法
hash = 31 * hash + str[i]; 其中str[i]表示string的某個位置字符 至於為什麽用31那。首先你必須使用一個質數,那又會問,為什麽要用質數呢,如果你使用一個有因數的數,那麽相乘得到的結果會出現更多的hash沖突。那為什麽選擇31呢,i*31== (i<<5)-1,可以被編譯器優化為移位計算,那為什麽不選7呢,i*7==(i<<3)-1,系數盡可能大也可以減少hash沖突,但是太大相乘可能會導致溢出,所以31是一個折中的系數。詳細可以參考這個解釋 https://stackoverflow.com/questions/299304/why-does-javas-hashcode-in-string-use-31-as-a-multiplierhash沖突解決方法
開放地址法
線性探測法
公式 比如二次探測法
可以不讓關鍵字都聚集在同一塊數據區域匯中(增加離散度)隨機探測法
需要註意的是,這個隨機數是一個偽隨機數,否則下次找不到hash值了再hash法
當遇到沖突時,對關鍵字再進行hash,可以采用不同的hash函數計算,目的是為了得到一個不沖突的hash值鏈表法
原理是不處理hash沖突的問題,就是讓它沖突,然後把沖突的關鍵字用鏈表串聯起來,下次找的時候直接遍歷鏈表就行了。多說一句,java的hashmap就是采用這個方法 拿圖來說就比如這樣公共溢出區
鏈表發是在每個位置上建立沖突的集合,而公共溢出區則為建立一個統一的沖突集合,這應該挺好理解。這適用用hash沖突較少的場景,如果多了,會影響性能,要知道遍歷鏈表的復雜度是O(n),還不如直接二分查找了。數據結構(十二)散列表