算法筆記(8)哈希

在M個數中查找某個數是否出現過,或者在一篇文章中查找一個單詞是否出現過,又或者需要統計一篇文章中某個單詞出現的次數,最直接的思維就是依據這個單詞遍歷整篇文章。顯然,這種算法的時間複雜度隨着文章篇幅的增多時間逐漸增加,那麼如何寫出一個常數級的查找算法呢?

哈希幫我們解決了這類問題。

簡單的,對於整數查找,我們可以利用bool數組以空間換時間的方式,統計次數則換用int類型即可。那麼,問題來了。對於過大的整數,單純靠消耗空間顯得極不明智。所以我們採取了散列函數,將一個較大的整數濃縮爲一個唯一的小整數(即H(key))。這裏對於整數哈希有幾種常見方法。

1.直接定址法

最常見最實用的方法,即H(key)=key或H(key)=a*key+b

2.平方取中法

H(key)爲key2的中間若干位,很少用。

3.除留取餘法

即將key除以一個數mod得到的餘數作爲哈希的方法。顯然,這樣可以把一個很大的數轉換爲不超過mod的整數,從而縮小了範圍。mod一般取素數便於覆蓋範圍內每一個數。

顯然,我們在使用這些方法的某些時不能保證H(key)相同的兩個key一定相等。我們又採取了一些方法來避免衝突。

1.線性探查法

當得到某個key的H(key)時,發現下標爲H(key)的位置已被佔領,那我們必須尋找新的hash,我們開始檢查當前的下一位,即H(key)+1,如果也被佔據,則以此類推,直到找到空閒位置爲止,當我們到表末尾時,則返回表頭繼續檢查即可。

2.平方探查法

爲了避免線性探查扎堆的現象,我們採用H(key)+12,H(key)-12,H(key)+22,H(key)-22的方式檢查,如果檢查過程中,H(key)+k2超過表長,則對錶長取模,如果H(key)-k2小於0,則不斷加表長直到其大於0爲止,如果想要避免負數帶來的麻煩,則可以只進行正向探查。

3.鏈地址法

前兩種由於指定了新的hash,所以稱爲開放定址法。這一種則將H(key)相同的所有key連接成單鏈表,並將多條這樣的鏈表放入一個數組,使得數組arr[H(key)]=list(key),這樣可以方便地查找H(key)的所有key值。

一般的,我們也會對字符或者字符串進行哈希。即將任意一個元素轉換爲唯一對應的整數,

對字符的哈希顯然可以利用ASCII碼,相比整數哈希更加簡單。

對於字符串,我們要考慮字符串中的字符種類,對於一串大寫字母字符串而言,一共26種字符,任意多個字符以任意方式組合,如果採用26進制 ,則每個字符串產生一個26進制數,如果將這個26進制數轉換爲10進制,即爲H(key)。同理,對其他字符類型組合也一樣。當初步得到唯一整數時,我們也可採用整數哈希來縮小整數範圍。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章