導航:首頁 > 使用方法 > 列出幾種常用的哈希函數構造方法

列出幾種常用的哈希函數構造方法

發布時間:2022-10-01 08:52:52

什麼是哈希演算法,哈希函數主要有哪些

額。。LZ是不是看了小說繪的終極解密啊?
我也蠻感興趣滴。。嘿嘿,
哈希函數是一般的線性表,樹中,記錄在結構中的相對位置是隨機的,即和記錄的關鍵字之間不存在確定的關系。
將數據元素的關鍵字K作為自變數,通過一定的函數關系(稱為哈希函數),計算出的值,即為該元素的存儲地址。表示為:
Addr = H(key)
為此在建立一個哈希表之前需要解決兩個主要問題:
⑴構造一個合適的哈希函數
均勻性 H(key)的值均勻分布在哈希表中;
簡單以提高地址計算的速度
⑵沖突的處理
沖突:在哈希表中,不同的關鍵字值對應到同一個存儲位置的現象。即關鍵字K1≠K2,但H(K1)= H(K2)。均勻的哈希函數可以減少沖突,但不能避免沖突。發生沖突後,必須解決;也即必須尋找下一個可用地址。 無論哈希函數設計有多麼精細,都會產生沖突現象,也就是2個關鍵字處理函數的結果映射在了同一位置上,因此,有一些方法可以避免沖突。
1.拉鏈
拉出一個動態鏈表代替靜態順序儲存結構,可以避免哈希函數的沖突,不過缺點就是鏈表的設計過於麻煩,增加了編程復雜度。此法可以完全避免哈希函數的沖突。
2.多哈希法
設計二種甚至多種哈希函數,可以避免沖突,但是沖突幾率還是有的,函數設計的越好或越多都可以將幾率降到最低(除非人品太差,否則幾乎不可能沖突)。
3.開放地址法
開放地址法有一個公式:Hi=(H(key)+di) MOD m i=1,2,...,k(k<=m-1)
其中,m為哈希表的表長。di 是產生沖突的時候的增量序列。如果di值可能為1,2,3,...m-1,稱線性探測再散列。
如果di取1,則每次沖突之後,向後移動1個位置.如果di取值可能為1,-1,2,-2,4,-4,9,-9,16,-16,...k*k,-k*k(k<=m/2)
稱二次探測再散列。如果di取值可能為偽隨機數列。稱偽隨機探測再散列。
4.建域法
假設哈希函數的值域為[0,m-1],則設向量HashTable[0..m-1]為基本表,另外設立存儲空間向量OverTable[0..v]用以存儲發生沖突的記錄。
LZ先把自己現階段的函數搞定,會慢慢接觸高等的函數滴,感覺蠻刺激的。。

⑵ 常用的構造哈希函數的方法有哪些

forName支持數組類型,loadClass不支持數組 一般情況下,這兩個方法效果一樣,都能裝載Class。但如果程序依賴於Class是否被初始化,就必須用Class.forName(name)了。 例如,在JDBC編程中,常看到這樣的用法,Class.forName("com.mysql.jdbc.Driver")

⑶ 哈希表、哈希演算法、一致性哈希表

    散列表(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的數據。由於這些虛擬節點數量很多,均勻分布,因此不會造成「雪崩」現象。

⑷ 常用的構造哈希函數的方法有哪些

forName支持數組類型,loadClass不支持數組
一般情況下,這兩個方法效果一樣,都能裝載Class。但如果程序依賴於Class是否被初始化,就必須用Class.forName(name)了。
例如,在JDBC編程中,常看到這樣的用法,Class.forName("com.mysql.jdbc.Driver")

⑸ 【區塊鏈與密碼學】第5-2講:哈希函數的構造

本節課程我們將詳細講解哈希函數的構造。

MASH-1 (Molar Arithmetic Secure Hash)是一個基於RSA演算法的哈希演算法,在1995年提出,入選國際標准ISO/IEC 10118-4;MASH-2是MASH-1的改進,把第四步中的2換成了28+1;由於涉及模乘/平方運算,計算速度慢,非常不實用。

分組密碼的工作模式是: 根據不同的數據格式和安全性要求, 以一個具體的分組密碼演算法為基礎構造一個分組密碼系統的方法。

基於分組的對稱密碼演算法比如DES/AES演算法只是描述如何根據秘鑰對一段固定長度(分組塊)的數據進行加密,對於比較長的數據,分組密碼工作模式描述了如何重復應用某種演算法安全地轉換大於塊的數據量。

簡單的說就是,DES/AES演算法描述怎麼加密一個數據塊,分組密碼工作模式模式了如果重復加密比較長的多個數據塊。常見的分組密碼工作模式有五種:

電碼本( Electronic Code Book,ECB)模式

密文分組鏈接(Cipher Block Chaining,CBC)模式

密文反饋(Cipher Feed Back ,CFB)模式

輸出反饋(Output Feed Back ,OFB)模式

計數器(Counter, CTR)模式

ECB工作模式

加密:輸入是當前明文分組。

解密:每一個密文分組分別解密。

具體公式為:

CBC工作模式

加密:輸入是當前明文分組和前一次密文分組的異或。

解密:每一個密文分組被解密後,再與前一個密文分組異或得明文。

具體公式為:

CFB工作模式

加密演算法的輸入是64比特移位寄存器,其初值為某個初始向量IV。

加密演算法輸出的最左(最高有效位)j比特與明文的第一個單元P1進行異或,產生出密文的第1個單元C1,並傳送該單元。

然後將移位寄存器的內容左移j位並將C1送入移位寄存器最右邊(最低有效位)j位。

這一過程繼續到明文的所有單元都被加密為止。

OFB工作模式

OFB模式的結構類似於CFB

不同之處:

OFB模式是將加密演算法的輸出反饋到移位寄存器

CFB模式中是將密文單元反饋到移位寄存器

CTR工作模式

加密:輸入是當前明文分組和計數器密文分組的異或。

解密:每一個密文分組被解密後,再與計數器密文分組異或得明文。

具體公式為:

工作模式比較

ECB模式,簡單、高速,但最弱、易受重發攻擊,一般不推薦。

CBC模式適用於文件加密,比ECB模式慢,安全性加強。當有少量錯誤時,不會造成同步錯誤。

OFB模式和CFB模式較CBC模式慢許多。每次迭代只有少數比特完成加密。若可以容忍少量錯誤擴展,則可換來恢復同步能力,此時用CFB或OFB模式。在字元為單元的流密碼中多選CFB模式。

CTR模式用於高速同步系統,不容忍差錯傳播。

直接設計哈希函數

Merkle在1989年提出迭代型哈希函數的一般結構;(另外一個工作是默克爾哈希樹),Ron Rivest在1990年利用這種結構提出MD4。(另外一個工作是RSA演算法),這種結構在幾乎所有的哈希函數中使用,具體做法為:

把所有消息M分成一些固定長度的塊Yi

最後一塊padding並使其包含消息M的長度

設定初始值CV0

循環執行壓縮函數f,CVi=f(CVi -1||Yi -1)

最後一個CVi為哈希值

演算法中重復使用一個壓縮函數f

f的輸入有兩項,一項是上一輪輸出的n比特值CVi-1,稱為鏈接變數,另一項是演算法在本輪的b比特輸入分組Yi-1

f的輸出為n比特值CVi,CVi又作為下一輪的輸入

演算法開始時還需對鏈接變數指定一個初值IV,最後一輪輸出的鏈接變數CVL即為最終產生的雜湊值

通常有b>n,因此稱函數f為壓縮函數

演算法可表達如下:CV0=IV= n比特長的初值

CVi=f(CVi-1,Yi-1);1≤i≤L

H(M)=CVL

演算法的核心技術是設計難以找到碰撞的壓縮函數f,而敵手對演算法的攻擊重點是f的內部結構

f和分組密碼一樣是由若干輪處理過程組成

對f的分析需要找出f的碰撞。由於f是壓縮函數,其碰撞是不可避免的,因此在設計f時就應保證找出其碰撞在計算上是困難的

哈希函數的構造就講到這里啦,以上三種方式都可以構造哈希函數。下節課我們將學習常用哈希函數,敬請期待!

⑹ 數據結構哈希演算法

1,直接定址法:
函數公式:f(key)=a*key+b (a,b為常數)
這種方法的優點是:簡單,均勻,不會產生沖突。但是需要事先知道關鍵字的分布情況,適合查找表較小並且連續的情況。
2,數字分析法:
比如我們的11位手機號碼「136XXXX7887」,其中前三位是接入號,一般對應不同運營公司的子品牌,如130是聯通如意通,136是移動神州行,153是電信等。中間四們是HLR識別號,表示用戶歸屬地。最後四們才是真正的用戶號。
若我們現在要存儲某家公司員工登記表,如果用手機號碼作為關鍵字,那麼極有可能前7位都是相同的,所以我們選擇後面的四們作為哈希地址就是不錯的選擇。
3,平方取中法:
故名思義,比如關鍵字是1234,那麼它的平方就是1522756,再抽取中間的3位就是227作為哈希地址。
4,折疊法:
折疊法是將關鍵字從左到右分割成位數相等的幾個部分(最後一部分位數不夠可以短些),然後將這幾部分疊加求和,並按哈希表表長,取後幾位作為哈希地址。
比如我們的關鍵字是9876543210,哈希表表長三位,我們將它分為四組,987|654|321|0 ,然後將它們疊加求和987+654+321+0=1962,再求後3位即得到哈希地址為962,哈哈,是不是很有意思。
5,除留余數法:
函數公式:f(key)=key mod p (p<=m)m為哈希表表長。
這種方法是最常用的哈希函數構造方法。
6,隨機數法:
函數公式:f(key)= random(key)。
這里random是隨機函數,當關鍵字的長度不等是,採用這種方法比較合適。
兩種哈希函數沖突解決方法
我們設計得最好的哈希函數也不可能完全避免沖突,當我們在使用哈希函數後發現兩個關鍵字key1!=key2,但是卻有f(key1)=f(key2),即發生沖突。

⑺ 哈希函數的哈希表的構造方法

有學生的生日數據如下:
年.月.日
75.10.03
75.11.23
76.03.02
76.07.12
75.04.21
76.02.15
...
經分析,第一位,第二位,第三位重復的可能性大,取這三位造成沖突的機會增加,所以盡量不取前三位,取後三位比較好。 將關鍵字分割成位數相同的幾部分(最後一部分的位數可以不同),然後取這幾部分的疊加和(捨去進位)作為哈希地址,這方法稱為折疊法。
例如:每一種西文圖書都有一個國際標准圖書編號,它是一個10位的十進制數字,若要以它作關鍵字建立一個哈希表,當館藏書種類不到10,000時,可採用此法構造一個四位數的哈希函數。 取關鍵字被某個不大於哈希表表長m的數p除後所得余數為哈希地址。
H(key)=key MOD p (p<=m) 選擇一個隨機函數,取關鍵字的隨機函數值為它的哈希地址,即
H(key)=random(key),其中random為隨機函數。通常用於關鍵字長度不等時採用此法。
若已知哈希函數及沖突處理方法,哈希表的建立步驟如下:
Step1.取出一個數據元素的關鍵字key,計算其在哈希表中的存儲地址D=H(key)。若存儲地址為D的存儲空間還沒有被佔用,則將該數據元素存入;否則發生沖突,執行Step2。
Step2.根據規定的沖突處理方法,計算關鍵字為key的數據元素之下一個存儲地址。若該存儲地址的存儲空間沒有被佔用,則存入;否則繼續執行Step2,直到找出一個存儲空間沒有被佔用的存儲地址為止。

⑻ 哈希表的常用方法

散列函數能使對一個數據序列的訪問過程更加迅速有效,通過散列函數,數據元素將被更快地定位。
實際工作中需視不同的情況採用不同的哈希函數,通常考慮的因素有:
· 計算哈希函數所需時間
· 關鍵字的長度
· 哈希表的大小
· 關鍵字的分布情況
· 記錄的查找頻率
1. 直接定址法:取關鍵字或關鍵字的某個線性函數值為散列地址。即H(key)=key或H(key) = a·key + b,其中a和b為常數(這種散列函數叫做自身函數)。若其中H(key)中已經有值了,就往下一個找,直到H(key)中沒有值了,就放進去。
2. 數字分析法:分析一組數據,比如一組員工的出生年月日,這時我們發現出生年月日的前幾位數字大體相同,這樣的話,出現沖突的幾率就會很大,但是我們發現年月日的後幾位表示月份和具體日期的數字差別很大,如果用後面的數字來構成散列地址,則沖突的幾率會明顯降低。因此數字分析法就是找出數字的規律,盡可能利用這些數據來構造沖突幾率較低的散列地址。
3. 平方取中法:當無法確定關鍵字中哪幾位分布較均勻時,可以先求出關鍵字的平方值,然後按需要取平方值的中間幾位作為哈希地址。這是因為:平方後中間幾位和關鍵字中每一位都相關,故不同關鍵字會以較高的概率產生不同的哈希地址。
例:我們把英文字母在字母表中的位置序號作為該英文字母的內部編碼。例如K的內部編碼為11,E的內部編碼為05,Y的內部編碼為25,A的內部編碼為01, B的內部編碼為02。由此組成關鍵字「KEYA」的內部代碼為11052501,同理我們可以得到關鍵字「KYAB」、「AKEY」、「BKEY」的內部編碼。之後對關鍵字進行平方運算後,取出第7到第9位作為該關鍵字哈希地址,如下圖所示 關鍵字 內部編碼 內部編碼的平方值 H(k)關鍵字的哈希地址 KEYA 11050201 122157778355001 778 KYAB 11250102 126564795010404 795 AKEY 01110525 001233265775625 265 BKEY 02110525 004454315775625 315
4. 折疊法:將關鍵字分割成位數相同的幾部分,最後一部分位數可以不同,然後取這幾部分的疊加和(去除進位)作為散列地址。數位疊加可以有移位疊加和間界疊加兩種方法。移位疊加是將分割後的每一部分的最低位對齊,然後相加;間界疊加是從一端向另一端沿分割界來回折疊,然後對齊相加。
5. 隨機數法:選擇一隨機函數,取關鍵字的隨機值作為散列地址,通常用於關鍵字長度不同的場合。
6. 除留余數法:取關鍵字被某個不大於散列表表長m的數p除後所得的余數為散列地址。即 H(key) = key MOD p,p<=m。不僅可以對關鍵字直接取模,也可在折疊、平方取中等運算之後取模。對p的選擇很重要,一般取素數或m,若p選的不好,容易產生同義詞。

⑼ 常見的哈希演算法有哪些

1、RSHash
unsigned int RSHash(const std::string& str)
{
unsigned int b = 378551;
unsigned int a = 63689;
unsigned int hash = 0;

for(std::size_t i = 0; i < str.length(); i++)
{
hash = hash * a + str[i];
a = a * b;
}

return hash;
}

2、JSHash
unsigned int JSHash(const std::string& str)
{
unsigned int hash = 1315423911;
for(std::size_t i = 0; i < str.length(); i++)
{
hash ^= ((hash << 5) + str[i] + (hash >> 2));
}
return hash;
}

3、PJWHash
unsigned int PJWHash(const std::string& str)
{
unsigned int BitsInUnsignedInt = (unsigned int)(sizeof(unsigned int) * 8);
unsigned int ThreeQuarters = (unsigned int)((BitsInUnsignedInt * 3) / 4);
unsigned int OneEighth = (unsigned int)(BitsInUnsignedInt / 8);
unsigned int HighBits = (unsigned int)(0xFFFFFFFF) << (BitsInUnsignedInt - OneEighth);
unsigned int hash = 0;
unsigned int test = 0;

for(std::size_t i = 0; i < str.length(); i++)
{
hash = (hash << OneEighth) + str[i];

if((test = hash & HighBits) != 0)
{
hash = (( hash ^ (test >> ThreeQuarters)) & (~HighBits));
}
}
return hash;
}

4、ELFHash
unsigned int ELFHash(const std::string& str)
{
unsigned int hash = 0;
unsigned int x = 0;

for(std::size_t i = 0; i < str.length(); i++)
{
hash = (hash << 4) + str[i];
if((x = hash & 0xF0000000L) != 0)
{
hash ^= (x >> 24);
}
hash &= ~x;
}

return hash;
}

5、BKDRHash
unsigned int BKDRHash(const std::string& str)
{
unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
unsigned int hash = 0;

for(std::size_t i = 0; i < str.length(); i++)
{
hash = (hash * seed) + str[i];
}
return hash;
}

哈希演算法將任意長度的二進制值映射為較短的固定長度的二進制值,這個小的二進制值稱為哈希值。哈希值是一段數據唯一且極其緊湊的數值表示形式。如果散列一段明文而且哪怕只更改該段落的一個字母,隨後的哈希都將產生不同的值。要找到散列為同一個值的兩個不同的輸入,在計算上是不可能的,所以數據的哈希值可以檢驗數據的完整性。一般用於快速查找和加密演算法。

閱讀全文

與列出幾種常用的哈希函數構造方法相關的資料

熱點內容
碧海金沙帳篷使用方法 瀏覽:463
2個大拇指好麻木用什麼方法治療 瀏覽:355
站立檢測骨盆前傾的方法 瀏覽:404
最簡單雙螺紋起針方法 瀏覽:252
種玉米的方法視頻 瀏覽:12
雙層樓梯尺寸計算方法 瀏覽:326
類風濕性關節炎的症狀及治療方法 瀏覽:490
vivo手機打電話黑屏在哪裡設置方法 瀏覽:300
分析設備設施的風險方法是 瀏覽:548
紅警2尤里的復仇兼容性解決方法 瀏覽:110
手工紅包小魚燈籠製作方法步驟及圖片 瀏覽:89
重量分析方法包括哪兩個過程 瀏覽:670
如何讓人記住你的方法短視頻 瀏覽:287
手機圖標隱藏功能在哪裡設置方法 瀏覽:30
樣本量少用什麼統計學方法 瀏覽:489
松下遙控器通用手機版使用方法 瀏覽:292
簡便計算的方法字母公式 瀏覽:899
核素敷貼治療方法 瀏覽:941
如何運用會計核算的方法 瀏覽:834
季度開票金額計算方法 瀏覽:33