一般來說,雜湊可以濃縮成一句話:將元素通過乙個函式轉化為整數,使得該整數可以盡量唯一地代表這個元素。其中,把這個轉換函式稱為雜湊函式h,也就是說,如果該元素在轉換前為key,那麼轉換後就是乙個整數h(key)
常見的雜湊函式有直接位址法、平方取中法、除留餘數法等。其中,直接位址法是指恒等變換h(key)=key或是線性變換(即h(key)=a*key+b),而平方取中法指取key的平方的中間若干位作為hash值(很少用),一般來說比較常用的是除留餘數法
除留餘數法:是指把key除以乙個數mod得到的餘數作為hash值的方法
通過這個函式,可以把很大的數轉化為不超過mod的整數,這樣就可以將它作為可行的陣列的下標(注意:表長tsize必須不小於mod,不然會產生越界)。顯然,當mod是乙個素數時,h(key)能盡可能覆蓋[0,mod)範圍內的每乙個數。
但是稍加思考就可以注意到:通過除留餘數法可能會有兩個不同的數key1和key2,它們的hash值是相同的,我們把這種情況叫做衝突
當得到key的hash值h(key),但是h(key)的位置已經被占用,那麼就檢查下乙個位置h(key)+1是否被占用,如果沒有,就使用這個位置,否則就繼續檢查下乙個位置,hash值再加1.如果hash值超過了表長,那麼就回到表的首位,繼續迴圈,直到找到乙個可用的位置或者表中的位置都已經被占用,顯然,這個做法容易導致扎堆,即連續若干個位置都已經被使用過,在一定程度上會降低效率。
在平方探測法中,為了盡可能避免扎堆現象,當表中下標為h(key)的位置被佔時,將按照下面的順序檢查表中的位置,h(key)+1^2,h(key)-1^2、h(key)+2^2,h(key)-2^2……,如果檢查過程中h(key)+k^2超過了表長tsize,那麼就把h(key)+k^2對錶長tsize取模,如果出現h(key)-k^2小於0的情況(假設表的首位為0),那麼將(h(key)-k^2)%tsize+tsize)%tsize作為結果(等價於h(key)-k^2不斷加上tsize直到出現第乙個非負數,如果想要避免負數的麻煩的麻煩,可以只進行正向的平方探測,可以證明,如果k在[0,tsize)範圍內無法找到位置,那麼當k>=tsize時,也一定無法找到位置
和上面兩種方法不同,鏈位址法不計算新的hash值,而是把所有h(key)相同的key連線成一條單鏈表。這樣可以設定乙個陣列link,範圍是link[0]~link[mod],其中,link[h]存放h(key)=h的一條單鏈表,於是當多個關鍵字key的hash值都是h時,就可以把這些衝突的key用單鏈表連線起來,此時就可以遍歷這條單鏈表來尋找h(key)=h的key值。
當然,一般來說,可以使用標準庫中的map來直接使用hash的功能,(c++11以後可以用unordered_map,速度更快),因此除非必須模擬這些方法或是對演算法的效率要求比較高,一般不需要自己實現上面解決衝突的方法
雜湊定義和整數雜湊 《演算法筆記》學習筆記
本文內容完全參考胡凡的 演算法筆記 目的自己學習一邊再記一下,方便本人日後複習 也本著分享的初衷給如我一樣的小白參考參考,在這裡推薦胡凡大佬的 演算法筆記 令我受益匪淺。問題 給出n個正整數,再給出m個正整數,問這m個數中每個數分別是否再n個數中出現過,其中n,m 最直接的思路是 對每個欲查詢的正整...
雜湊表(雜湊表)的定義
chapter 雜湊表 雜湊表 1.雜湊表 雜湊表 的定義 2.雜湊表是怎麼進行查詢的?3.雜湊函式設計 直接定址法 4.雜湊函式設計 除留餘數法 5.雜湊衝突處理 開放定址法 6.雜湊衝突處理 鏈位址法 7.雜湊表的鏈位址法實現 8.linux核心中的hash與bucket 9.引入雜湊桶的概念來...
雜湊表(雜湊表)的定義
到了有序表 已排序的表 查詢時,我們可以利用a i 與key的 或 來折半查詢,直到相等時查詢成功返回i。反正我們的目標就是要找到那個 i 值,是不是還有其它好點的方法呢?乙個小故事 試想這樣的場景,你很想學太極拳,聽說學校有個叫張三丰的人打得特別好,於是你到學校學生處找人。學生處的工作人員可能會拿...