Ⅰ hash演算法
有一點你搞錯了。Hash演算法不是為了快速找出相同的元素,而是為了快速判斷兩個元素不相等。
所有散列函數都有如下一個基本特性:如果兩個散列值是不相同的(根據同一函數),那麼這兩個散列值的原始輸入也是不相同的。這個特性是散列函數具有確定性的結果。但另一方面,散列函數的輸入和輸出不是一一對應的,如果兩個散列值相同,兩個輸入值很可能是相同的,但並不能絕對肯定二者一定相等。
例如:設計一個針對字元串的Hash演算法,簡單地返回字元串的首字母:
def Hash_string(str):
return str[0]
那麼:
Hash_string(a)=Hash(gfdgfd)=g
Hash_string(b)=Hash(xzcfs)=x
這樣就可以最快速地判斷出兩個字元串不相等。這個Hash演算法常用於將大量文件分散存儲。
對於首字母相同的兩個字元串,本演算法得到的Hash值肯定相同,這就是出現了命中沖突。解決命中沖突有很多策略,比如:再散列法、鏈地址法、公共溢出法……等等。
一個好的Hash演算法,應該保證高命中率和均勻分布。
Ⅱ 如何解決Hash中的沖突問題
1、開放定址法
用開放定址法解決沖突的做法是:當沖突發生時,使用某種探查(亦稱探測)技術在散列表中形成一個探查(測)序列。沿此序列逐個單元地查找,直到找到給定 的關鍵字,或者碰到一個開放的地址(即該地址單元為空)為止(若要插入,在探查到開放的地址,則可將待插入的新結點存人該地址單元)。查找時探查到開放的 地址則表明表中無待查的關鍵字,即查找失敗。注意:
①用開放定址法建立散列表時,建表前須將表中所有單元(更嚴格地說,是指單元中存儲的關鍵字)置空。
②空單元的表示與具體的應用相關。
按照形成探查序列的方法不同,可將開放定址法區分為線性探查法、線性補償探測法、隨機探測等。
(1)線性探查法(Linear Probing)
該方法的基本思想是:
將散列表T[0..m-1]看成是一個循環向量,若初始探查的地址為d(即h(key)=d),則最長的探查序列為:
d,d+l,d+2,…,m-1,0,1,…,d-1
即:探查時從地址d開始,首先探查T[d],然後依次探查T[d+1],…,直到T[m-1],此後又循環到T[0],T[1],…,直到探查到 T[d-1]為止。
探查過程終止於三種情況:
(1)若當前探查的單元為空,則表示查找失敗(若是插入則將key寫入其中);
(2)若當前探查的單元中含有key,則查找成功,但對於插入意味著失敗;
(3)若探查到T[d-1]時仍未發現空單元也未找到key,則無論是查找還是插入均意味著失敗(此時表滿)。
利用開放地址法的一般形式,線性探查法的探查序列為:
hi=(h(key)+i)%m 0≤i≤m-1 //即di=i
用線性探測法處理沖突,思路清晰,演算法簡單,但存在下列缺點:
① 處理溢出需另編程序。一般可另外設立一個溢出表,專門用來存放上述哈希表中放不下的記錄。此溢出表最簡單的結構是順序表,查找方法可用順序查找。
② 按上述演算法建立起來的哈希表,刪除工作非常困難。假如要從哈希表 HT 中刪除一個記錄,按理應將這個記錄所在位置置為空,但我們不能這樣做,而只能標上已被刪除的標記,否則,將會影響以後的查找。
③ 線性探測法很容易產生堆聚現象。所謂堆聚現象,就是存入哈希表的記錄在表中連成一片。按照線性探測法處理沖突,如果生成哈希地址的連續序列愈長 ( 即不同關鍵字值的哈希地址相鄰在一起愈長 ) ,則當新的記錄加入該表時,與這個序列發生沖突的可能性愈大。因此,哈希地址的較長連續序列比較短連續序列生長得快,這就意味著,一旦出現堆聚 ( 伴隨著沖突 ) ,就將引起進一步的堆聚。
(2)線性補償探測法
線性補償探測法的基本思想是:
將線性探測的步長從 1 改為 Q ,即將上述演算法中的 j = (j + 1) % m 改為: j = (j + Q) % m ,而且要求 Q 與 m 是互質的,以便能探測到哈希表中的所有單元。
【例】 PDP-11 小型計算機中的匯編程序所用的符合表,就採用此方法來解決沖突,所用表長 m = 1321 ,選用 Q = 25 。 2、拉鏈法
(1)拉鏈法解決沖突的方法
拉鏈法解決沖突的做法是:將所有關鍵字為同義詞的結點鏈接在同一個單鏈表中。若選定的散列表長度為m,則可將散列表定義為一個由m個頭指針組成的指針數 組T[0..m-1]。凡是散列地址為i的結點,均插入到以T[i]為頭指針的單鏈表中。T中各分量的初值均應為空指針。在拉鏈法中,裝填因子α可以大於 1,但一般均取α≤1。
【例】設有 m = 5 , H(K) = K mod 5 ,關鍵字值序例 5 , 21 , 17 , 9 , 15 , 36 , 41 , 24 ,按外鏈地址法所建立的哈希表如下圖所示:
(2)拉鏈法的優點
與開放定址法相比,拉鏈法有如下幾個優點:
①拉鏈法處理沖突簡單,且無堆積現象,即非同義詞決不會發生沖突,因此平均查找長度較短;
②由於拉鏈法中各鏈表上的結點空間是動態申請的,故它更適合於造表前無法確定表長的情況;
③開放定址法為減少沖突,要求裝填因子α較小,故當結點規模較大時會浪費很多空間。而拉鏈法中可取α≥1,且結點較大時,拉鏈法中增加的指針域可忽略不計,因此節省空間;
④在用拉鏈法構造的散列表中,刪除結點的操作易於實現。只要簡單地刪去鏈表上相應的結點即可。而對開放地址法構造的散列表,刪除結點不能簡單地將被刪結 點的空間置為空,否則將截斷在它之後填人散列表的同義詞結點的查找路徑。這是因為各種開放地址法中,空地址單元(即開放地址)都是查找失敗的條件。因此在 用開放地址法處理沖突的散列表上執行刪除操作,只能在被刪結點上做刪除標記,而不能真正刪除結點。
(3)拉鏈法的缺點
拉鏈法的缺點是:指針需要額外的空間,故當結點規模較小時,開放定址法較為節省空間,而若將節省的指針空間用來擴大散列表的規模,可使裝填因子變小,這又減少了開放定址法中的沖突,從而提高平均查找速度。
Ⅲ 什麼是哈希沖突
哈希計算就是努力的把比較大的數據存放到相對較小的空間中。
最常見的哈希演算法是取模法。
下面簡單講講取模法的計算過程。
比如:數組的長度是5。這時有一個數據是6。那麼如何把這個
6存放到長度只有5的數組中呢。按照取模法,計算
6%5,結果是1,那麼就把6放到數組下標是1的位置。那麼,7
就應該放到2這個位置。到此位置,哈斯沖突還沒有出現。
這時,有個數據是11,按照取模法,11%5=1,也等於1。那麼
原來數組下標是1的地方已經有數了,是6。這時又計算出1這個
位置,那麼數組1這個位置,就必須儲存兩個數了。這時,就叫
哈希沖突。沖突之後就要按照順序來存放了。
如果數據的分布比較廣泛,而且儲存數據的數組長度比較大。
那麼哈希沖突就比較少。否則沖突是很高的。
具體的演算法你要參照更加專業的書籍。
希望對你有幫助。
Ⅳ hash演算法不發生沖突的概率
hash演算法的發生沖突的概率較小。由於hash的原理是將輸入空間的值映射成hash空間內,而hash值的空間遠小於輸入的空間。
Ⅳ hash演算法是什麼
Hash,就是把任意長度的輸入(又叫做預映射,pre-image),通過散列演算法,變換成固定長度的輸出,該輸出就是散列值。這種轉換是一種壓縮映射,也就是,散列值的空間通常遠小於輸入的空間,不同的輸入可能會散列成相同的輸出,而不可能從散列值來唯一的確定輸入值。簡單的說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數。
使用哈希查找有兩個步驟:
1、使用哈希函數將被查找的鍵轉換為數組的索引。在理想的情況下,不同的鍵會被轉換為不同的索引值,但是在有些情況下我們需要處理多個鍵被哈希到同一個索引值的情況。所以哈希查找的第二個步驟就是處理沖突。
2、處理哈希碰撞沖突。有很多處理哈希碰撞沖突的方法,本文後面會介紹拉鏈法和線性探測法。
Ⅵ 哈希值為什麼會沖突
1、哈希就是做一個映射,為的是查找快.沖突是zd因為映射畢竟是有一個范圍的,這個范圍可能會小於你原來的那個范圍,所以可能好多個值映射了之後成為一個值了.
舉例來說,可能希望查版找字元串比較快,你會用一種計算方法將一個字元串權映射為一個整數,而且要求這個數字在100以內.那麼如果處理了10000個字元串,他們映射的值肯定會沖突.
2、hash:hashing定義了一種百將字元組成的字元串轉換為固定長度度(一般是更短長度)的數值或索引值的方法,稱為問散列法,也叫哈希法。
沖突:兩個不同的關答鍵字,由於散列函數值相同,因而被內映射到同一表位置上。該容現象稱為沖突(collision)或碰撞。
3、哈希計算就是努力的把比較大的數據存放到相百對較小的空間中。
最常見的哈希演算法是取模法。
下面簡單講講取模法的計算過程。
比如:數組的長度是5。這時有度一個數據是6。那麼如何把這個
6存放到長度只有5的數組中呢。按照取模法,計算
6%5,結果是1,那麼就把6放到數組下標是1的位問置。那麼,7
就應該放到2這個位置。到此位置,哈希沖突還沒有出現。
這時,有個數據是11,按照取模法,11%5=1,也等於1。那麼
原來數組下標是1的地方已經有數了答,是6。這時又計算出1這個
位置,那麼數組1這個位置,就回必須儲存兩個數了。這時,就叫
哈希答沖突。沖突之後就要按照順序來存放了。
如果數據的分布比較廣泛,而且儲存數據的數組長度比較大。
那麼哈希沖突就比較少。否則沖突是很高的。
具體的演算法你要參照更加專業的書籍。
希望對你有幫助。
出自:網路知道
Ⅶ redis使用什麼演算法來解決hash沖突
因為Memcached的哈希策略是在其客戶端實現的,因此不同的客戶端實現也有區別,以Spymemcache、Xmemcache為例,都是使用了KETAMA作為其實現。
因此,我們也可以使用一致性hash演算法來解決Redis分布式這個問題。在介紹一致性hash演算法之前,先介紹一下我之前想的一個方法,怎麼把Key均勻的映射到多台Redis Server上。
Ⅷ 解決hash沖突的三個方法
通過構造性能良好的哈希函數,可以減少沖突,但一般不可能完全避免沖突,因此解決沖突是哈希法的另一個關鍵問題。創建哈希表和查找哈希表都會遇到沖突,兩種情況下解決沖突的方法應該一致。下面以創建哈希表為例,說明解決沖突的方法。常用的解決沖突方法有以下四種:
開放定址法
這種方法也稱再散列法,其基本思想是:當關鍵字key的哈希地址p=H(key)出現沖突時,以p為基礎,產生另一個哈希地址p1,如果p1仍然沖突,再以p為基礎,產生另一個哈希地址p2,…,直到找出一個不沖突的哈希地址pi ,將相應元素存入其中。這種方法有一個通用的再散列函數形式:
其中H(key)為哈希函數,m 為表長,di稱為增量序列。增量序列的取值方式不同,相應的再散列方式也不同。主要有以下三種:
線性探測再散列
這種方法的特點是:沖突發生時,順序查看錶中下一單元,直到找出一個空單元或查遍全表。
二次探測再散列
這種方法的特點是:沖突發生時,在表的左右進行跳躍式探測,比較靈活。
偽隨機探測再散列
具體實現時,應建立一個偽隨機數發生器,(如i=(i+p) % m),並給定一個隨機數做起點。
例如,已知哈希表長度m=11,哈希函數為:H(key)= key % 11,則H(47)=3,H(26)=4,H(60)=5,假設下一個關鍵字為69,則H(69)=3,與47沖突。
如果用線性探測再散列處理沖突,下一個哈希地址為H1=(3 + 1)% 11 = 4,仍然沖突,再找下一個哈希地址為H2=(3 + 2)% 11 = 5,還是沖突,繼續找下一個哈希地址為H3=(3 + 3)% 11 = 6,此時不再沖突,將69填入5號單元。
如果用二次探測再散列處理沖突,下一個哈希地址為H1=(3 + 12)% 11 = 4,仍然沖突,再找下一個哈希地址為H2=(3 - 12)% 11 = 2,此時不再沖突,將69填入2號單元。
如果用偽隨機探測再散列處理沖突,且偽隨機數序列為:2,5,9,……..,則下一個哈希地址為H1=(3 + 2)% 11 = 5,仍然沖突,再找下一個哈希地址為H2=(3 + 5)% 11 = 8,此時不再沖突,將69填入8號單元。
再哈希法
這種方法是同時構造多個不同的哈希函數:
當哈希地址Hi=RH1(key)發生沖突時,再計算Hi=RH2(key)……,直到沖突不再產生。這種方法不易產生聚集,但增加了計算時間。
鏈地址法
這種方法的基本思想是將所有哈希地址為i的元素構成一個稱為同義詞鏈的單鏈表,並將單鏈表的頭指針存在哈希表的第i個單元中,因而查找、插入和刪除主要在同義詞鏈中進行。鏈地址法適用於經常進行插入和刪除的情況。
建立公共溢出區
這種方法的基本思想是:將哈希表分為基本表和溢出表兩部分,凡是和基本表發生沖突的元素,一律填入溢出表。
優缺點
開放散列(open hashing)/ 拉鏈法(針對桶鏈結構)
優點:
缺點:
封閉散列(closed hashing)/ 開放定址法
優點:
缺點:
Ⅸ hash沖突的方法
當沖突發生後,直接去下一個位置找是否存在沒用的位置,例如2位置發生沖突,然後去下一位置3查找,如果3也被佔用,去找4,直到問題解決
未發生沖突前
直到現在2插入,發現2位置上上是5,已經有值,所以去找下一個發現沒有了,緊接著直接擴容和線性探測
後面4插入時,先去看1,發現有1,看2發現有5,看3發現有2,擴容插入4
可以看到非常容易產生一次聚類
以上為例:
當2發現發生沖突時直接每次增長i^2 倍,即2(hash值)+(-) i^2
當4發生沖突,先是尋找2(1+1^2)再尋找5(1+ 2^2)
發生沖突:如果用偽隨機探測再散列處理沖突,且偽隨機數序列為:2,5,9,……..,則下一個哈希地址為H1=(3 + 2)% 11 = 5,仍然沖突,再找下一個哈希地址為H2=(3 + 5)% 11 = 8,此時不再沖突,將69填入8號單元
這種方法是同時構造多個不同的哈希函數:
Hi=RH1(key) i=1,2,…,k
當哈希地址Hi=RH1(key)發生沖突時,再計算Hi=RH2(key)……,直到沖突不再產生。這種方法不易產生聚集,但增加了計算時間。
在我hashcode的後面建立一個鏈表,每一個鏈表表示現在hashcode為當前的所有元素
但是這個方法很容易就造成鏈表的長度過大,在訪問時候可能會時間很長,
所有適時的要增大數組的長度。來換取鏈表的長度
例如上面是mod3,我們可以mod5
什麼時候擴容?
「我們可以定義這樣一個變數 α = 所有元素個數/數組的大小,我們叫它裝載因子吧,它代表著我們的Hash表(也就是數組)的裝滿程度,在這里也代表鏈表的平均長度
例如上面的 數組{5,1,3,2,4} 當取mod3時候就是 α = 5%3,這時候我們擴容
即使Hash函數設計的合理,基本上每次存放元素的時候就會沖突,所以鑒於兩者之間我覺得 0.6 - 0.9 之間是一個不錯的選擇,不妨選0.75吧」
參考: https://cloud.tencent.com/developer/article/1361248