當前位置:編程學習大全網 - 編程語言 - 哈希表、哈希算法、壹致性哈希表

哈希表、哈希算法、壹致性哈希表

散列表(Hash table,也叫哈希表),是根據關鍵碼值(Key value)而直接進行訪問的數據結構。它通過把關鍵碼映射到表中壹個位置來訪問記錄,以加快查找的速度。這個映射函數叫做散列函數(哈希函數),存放記錄的數組叫做散列表。

? 優點:

哈希表可以提供快速的操作。

缺點:

哈希表通常是基於數組的,數組創建後難於擴展。

也沒有壹種簡便的方法可以以任何壹種順序〔例如從小到大)遍歷表中的數據項 。

綜上, 如果不需要有序遍歷數據,井且可以提前預測數據量的大小。那麽哈希表在速度和易用性方面是無與倫比的。

1.?使用哈希函數將被查找的鍵轉換為數組的索引。

2.?處理哈希碰撞沖突。

若關鍵字為 k ,則其值存放在 f(k) 的存儲位置上。由此,不需比較便可直接取得所查記錄。稱這個對應關系 f 為散列函數,按這個思想建立的表為散列表。

若對於關鍵字集合中的任壹個關鍵字,經散列函數映象到地址集合中任何壹個地址的概率是相等的,則稱此類散列函數為 均勻散列函數 (Uniform Hash function),這就是使關鍵字經過散列函數得到壹個"隨機的地址",從而減少碰撞。

散列函數能使對壹個數據序列的訪問過程更加迅速有效,通過散列函數,數據元素將被更快地定位。

壹個好的散列函數壹般應該考慮下列因素 :

1.計算簡單,以便提高轉換速度。

2.關鍵詞對應的地址空間分布均勻,以盡量減少沖突。

1.? 直接尋址法

取關鍵字或者關鍵字的某個線性函數值作為哈希地址,即H(Key)=Key或者H(Key)=a*Key+b(a,b為整數),這種散列函數也叫做自身函數.如果H(Key)的哈希地址上已經有值了,那麽就往下壹個位置找,直到找到H(Key)的位置沒有值了就把元素放進去。

2.? 數字分析法

數字分析法就是找出數字的規律,盡可能利用這些數據來構造沖突幾率較低的散列地址。

3.? 平方取中法

取關鍵字平方後的中間幾位作為散列地址。這種方法的原理是通過取平方擴大差別,平方值的中間幾位和這個數的每壹位都相關,則對不同的關鍵字得到的哈希函數值不易產生沖突,由此產生的哈希地址也較為均勻。該方法適用於關鍵字中的每壹位都有某些數字重復出現頻度很高的現象。

4.? 折疊法

折疊法是將關鍵字分割成位數相同的幾部分,最後壹部分位數可以不同,然後取這幾部分的疊加和(註意:疊加和時去除進位)作為散列地址。

數位疊加可以有移位疊加和間界疊加兩種方法。移位疊加是將分割後的每壹部分的最低位對齊,然後相加;間界疊加是從壹端向另壹端沿分割界來回折疊,然後對齊相加。

該方法適用於關鍵字特別多的情況。

5.? 隨機數法

選擇壹個隨機數,作為散列地址,通常用於關鍵字長度不同的場合。

6.? 除留余數法

取關鍵字被某個不大於散列表表長m的數p除後所得的余數為散列地址.即H(Key)=Key MOD p,p<=m.不僅可以對關鍵字直接取模,也可在折疊、平方取中等運算之後取模。對p的選擇很重要,壹般取素數或m,若p選得不好,則很容易產生沖突。

對不同的關鍵字可能得到同壹散列地址,即 k1≠k2 ,而 f(k1)=f(k2) ,這種現象稱為碰撞(英語:Collision)。具有相同函數值的關鍵字對該散列函數來說稱做同義詞。

通過構造性能良好的散列函數,可以減少沖突,但壹般不可能完全避免沖突,因此解決沖突是哈希法的另壹個關鍵問題。 創建哈希表和查找哈希表都會遇到沖突,兩種情況下解決沖突的方法應該壹致。

下面以創建哈希表為例,說明解決沖突的方法。

1.開放定址法

這種方法也稱再散列法,其基本思想是:當關鍵字key的哈希地址p=H(key)出現沖突時,以p為基礎,產生另壹個哈希地址p1,如果p1仍然沖突,再以p為基礎,產生另壹個哈希地址p2,…,直到找出壹個不沖突的哈希地址pi ,將相應元素存入其中。這種方法有壹個通用的再散列函數形式:Hi=(H(key)+di)%m? i=1,2,…,m-1,其中H(key)為哈希函數,m 為表長,di稱為增量序列,i為碰撞次數。增量序列的取值方式不同,相應的再散列方式也不同。增量序列主要有以下幾種:

(1)?線性探測再散列

di=1,2,3,…,m-1

這種方法的特點是:沖突發生時,順序查看表中下壹單元,直到找出壹個空單元或查遍全表。

(2)二次探測再散列

di=12,-12,22,-22,…,k2,-k2( k<=m/2 )

這種方法的特點是:沖突發生時,在表的左右進行跳躍式探測,比較靈活。

(3)偽隨機探測再散列

di=偽隨機數序列。

線性探測再散列的 優點 是:只要哈希表不滿,就壹定能找到壹個不沖突的哈希地址,而二次探測再散列和偽隨機探測再散列則不壹定。線性探測再散列容易產生“二次聚集”,即在處理同義詞的沖突時又導致非同義詞的沖突。

其實除了上面的幾種方法,開放定址法還有很多變種,不過都是對di有不同的表示方法。(如雙散列探測法:di=i*h2(k))

2.再哈希法

這種方法是同時構造多個不同的哈希函數:Hi=RHi(key),i=1,2,3,…,n。

當哈希地址H1=RH1(key)發生沖突時,再計算H2=RH2(key)……,直到沖突不再產生。這種方法不易產生聚集,但增加了計算時間。

?3.鏈地址法(拉鏈法)

這種方法的基本思想是將所有哈希地址相同的元素構成壹個稱為同義詞鏈的單鏈表,並將單鏈表的頭指針存在哈希表(數組)中,因而查找、插入和刪除主要在同義詞鏈中進行。若選定的散列表長度為m,則可將散列表定義為壹個由m個頭指針組成的指針數組T[0..m-1]。凡是散列地址為i的結點,均插入到以T[i]為頭指針的單鏈表中。T中各分量的初值均應為空指針。鏈地址法適用於經常進行插入和刪除的情況。

拉鏈法的優點

與開放定址法相比,拉鏈法有如下幾個優點:

(1)拉鏈法處理沖突簡單,且無堆積現象,即非同義詞決不會發生沖突,因此平均查找長度較短;

(2)由於拉鏈法中各鏈表上的結點空間是動態申請的,故它更適合於造表前無法確定表長的情況;

(3)開放定址法為減少沖突,要求裝填因子α較小,故當結點規模較大時會浪費很多空間。而拉鏈法中理論上可取α≥1,且結點較大時,拉鏈法中增加的指針域可忽略不計,因此節省空間;(散列表的裝填因子定義為:α= 填入表中的元素個數 / 散列表的長度)

註:HashMap默認裝填因子是0.75。

(4)在用拉鏈法構造的散列表中,刪除結點的操作易於實現。只要簡單地刪去鏈表上相應的結點即可。而對開放定址法構造的散列表,刪除結點不能簡單地將被刪結點的空間置為空,否則將截斷在它之後填入散列表的同義詞結點的查找路徑。這是因為各種開放定址法中,空地址單元都被理解沒有查找到元素。 因此在用開放定址法處理沖突的散列表上執行刪除操作,只能在被刪結點上做刪除標記,而不能真正刪除結點。

拉鏈法的缺點

拉鏈法的缺點是:指針需要額外的空間,故當結點規模較小時,開放定址法較為節省空間,此時將節省的指針空間用來擴大散列表的規模,可使裝填因子變小,這又減少了開放定址法中的沖突,從而提高平均查找速度。

4、建立公***溢出區

這種方法的基本思想是:將哈希表分為基本表和溢出表兩部分,凡是和基本表發生沖突的元素,壹律填入溢出表(在這個方法裏面是把元素分開兩個表來存儲)。

散列表的查找過程基本上和造表過程相同。壹些關鍵碼可通過散列函數轉換的地址直接找到,另壹些關鍵碼在散列函數得到的地址上產生了沖突,需要按處理沖突的方法進行查找。在介紹的三種處理沖突的方法中,產生沖突後的查找仍然是給定值與關鍵碼進行比較的過程。所以,對散列表查找效率的量度,依然用平均查找長度來衡量。

查找過程中,關鍵碼的比較次數,取決於產生沖突的多少,產生的沖突少,查找效率就高,產生的沖突多,查找效率就低。因此,影響產生沖突多少的因素,也就是影響查找效率的因素。

影響產生沖突多少有以下三個因素:

1. 散列函數是否均勻;

2. 處理沖突的方法;

3. 散列表的裝填因子。

散列表的裝填因子

定義為:α= 填入表中的元素個數 / 散列表的長度

α是散列表裝滿程度的標誌因子。由於表長是定值,α與"填入表中的元素個數"成正比,所以,α越大,填入表中的元素較多,產生沖突的可能性就越大;α越小,填入表中的元素較少,產生沖突的可能性就越小。

實際上,散列表的平均查找長度是裝填因子α的函數,只是不同處理沖突的方法有不同的函數。

這個HASH算法不是大學裏數據結構課裏那個HASH表的算法。這裏的HASH算法是密碼學的基礎,了解了hash基本定義,就不能不提到壹些著名的hash算法,MD5 和 SHA-1 可以說是目前應用最廣泛的Hash算法,而它們都是以 MD4 為基礎設計的。

Hash算法在信息安全方面的應用主要體現在以下的3個方面:

⑴? 文件校驗

我們比較熟悉的校驗算法有奇偶校驗和CRC校驗,這2種校驗並沒有抗 數據篡改 的能力,它們壹定程度上能檢測出數據傳輸中的信道誤碼,但卻不能防止對數據的惡意破壞。

MD5 Hash算法的"數字指紋"特性,使它成為目前應用最廣泛的壹種文件完整性 校驗和 (Checksum)算法,不少Unix系統有提供計算md5 checksum的命令。

⑵? 數字簽名

Hash 算法也是現代密碼體系中的壹個重要組成部分。由於非對稱算法的運算速度較慢,所以在 數字簽名 協議中,單向散列函數扮演了壹個重要的角色。對 Hash 值,又稱"數字摘要"進行數字簽名,在統計上可以認為與對文件本身進行數字簽名是等效的。而且這樣的協議還有其他的優點。

? ⑶ 鑒權協議

如下的鑒權協議又被稱作挑戰--認證模式:在傳輸信道是可被偵聽,但不可被篡改的情況下,這是壹種簡單而安全的方法。

壹致性哈希表簡稱DHT,主要應用於分布式緩存中,可以用來解決分布式存儲結構下動態增加和刪除節點所帶來的問題。比如,壹個分布式的存儲系統,要將數據存儲到具體的節點上,如果采用普通的hash方法,將數據映射到具體的節點上,如key%N(key是數據的key,N是機器節點數),如果有壹個機器加入或退出這個集群,則所有的數據映射都無效了,如果是持久化存儲則要做數據遷移,如果是分布式緩存,則其他緩存就失效了。

判定哈希算法好壞的四個定義 :

1、平衡性(Balance):平衡性是指哈希的結果能夠盡可能分布到所有的緩沖中去,這樣可以使得所有的緩沖空間都得到利用。

2、單調性(Monotonicity):單調性是指如果已經有壹些內容通過哈希分派到了相應的緩沖中,又有新的緩沖加入到系統中。哈希的結果應能夠保證原有已分配的內容可以被映射到原有的或者新的緩沖中去,而不會被映射到舊的緩沖集合中的其他緩沖區。

3、分散性(Spread):在分布式環境中,終端有可能看不到所有的緩沖,而是只能看到其中的壹部分。當終端希望通過哈希過程將內容映射到緩沖上時,由於不同終端所見的緩沖範圍有可能不同,從而導致哈希的結果不壹致,最終的結果是相同的內容被不同的終端映射到不同的緩沖區中。這種情況顯然是應該避免的,因為它導致相同內容被存儲到不同緩沖中去,降低了系統存儲的效率。 分散性的定義就是上述情況發生的嚴重程度。好的哈希算法應能夠盡量避免不壹致的情況發生,也就是盡量降低分散性。

4、負載(Load):負載問題實際上是從另壹個角度看待分散性問題。既然不同的終端可能將相同的內容映射到不同的緩沖區中,那麽對於壹個特定的緩沖區而言,也可能被不同的用戶映射為不同的內容。與分散性壹樣,這種情況也是應當避免的, 因此好的哈希算法應能夠盡量降低緩沖的負荷。

在分布式集群中,對機器的添加刪除,或者機器故障後自動脫離集群這些操作是分布式集群管理最基本的功能。如果采用常用的hash取模算法,那麽在有機器添加或者刪除後,很多原有的數據就無法找到了,這樣嚴重的違反了單調性原則。接下來主要說明壹下壹致性哈希算法是如何設計的。

以SpyMemcached的ketama算法來說,思路是這樣的:

把數據用hash函數,映射到壹個很大的空間裏,如圖所示。數據的存儲時,先得到壹個hash值,對應到這個環中的每個位置,如k1對應到了圖中所示的位置,然後沿順時針找到壹個機器節點B,將k1存儲到B這個節點中。

如果B節點宕機了,則B上的數據就會落到C節點上,如下圖所示:

這樣,只會影響C節點,對其他的節點A,D的數據不會造成影響。然而,這又會造成壹個“雪崩”的情況,即C節點由於承擔了B節點的數據,所以C節點的負載會變高,C節點很容易也宕機,這樣依次下去,這樣造成整個集群都掛了。

為此,引入了“虛擬節點”的概念:即把想象在這個環上有很多“虛擬節點”,數據的存儲是沿著環的順時針方向找壹個虛擬節點,每個虛擬節點都會關聯到壹個真實節點,如下圖所使用:

圖中的A1、A2、B1、B2、C1、C2、D1、D2都是虛擬節點,機器A負載存儲A1、A2的數據,機器B負載存儲B1、B2的數據,機器C負載存儲C1、C2的數據。由於這些虛擬節點數量很多,均勻分布,因此不會造成“雪崩”現象。

  • 上一篇:左腦和右腦各有什麽作用?
  • 下一篇:廣西工業職業技術學院什麽時候才發通知書
  • copyright 2024編程學習大全網