Hash(哈希)相關知識(哈希函數、哈希查找)

前言

  • 因爲本人是小白(小菜雞),所以有些地方說的可能不是很準確,大家可以參考一些很厲害的博主,在評論區指出我寫的不對的地方。
  • 本來是想要單獨寫一下Hash(哈希)查找算法,但後來想到Java和區塊鏈的入門裏面都涉及到Hash,所以就說一下自己對Hash的理解。
  • 在寫的過程中,有涉及到密碼學的相關概念,我盡力用舉例子的方式讓讀者明白,如果覺得我有哪裏說的不準確,可以查找相關文獻進行更深層次的理解,以免我誤人子弟,順便謝謝大家啦!

一. 哈希函數

1. 函數特性

1.1 基本的哈希函數

  • 哈希函數是一個數學函數,特性有下面三點:
  • 其輸入可爲任意大小的字符串。
  • 它產生固定大小的輸出。
  • 它能進行有效的計算,就是說對於特定的輸入字符串,在合理時間內,能夠計算出哈希函數的輸出,對n位的字符串,哈希值計算的複雜度是O(n)。

1.2 加密的哈希函數

  • 主要有附加的三個特性(相關文字說明源於BITCOIN AND CRYPTOCURRENCY TECHNOLOGIES 區塊鏈技術驅動金融-數字貨幣與智能合約技術):
  • 碰撞阻力:對於兩個不同的輸入,能夠產生相同的輸出,就像y=x2,key1≠key2,但是產生了H(key1)=H(key2)。實際上世界上根本不存在具有防碰撞特性的哈希函數,現在技術上所用的加密哈希函數只不過是還沒有找到碰撞的函數,就像之前人們都用的MD5,在前幾年找到了碰撞後就逐漸淡出市場。
  • 隱祕性:如果我們無法通過輸出y=H(x)來找到輸入x,那麼就保證了隱祕性。但要滿足這樣條件的x必須取自一個非常大的集合,否則x將很容易就被獲取。例如,我們拋硬幣,只需要知道結果就很容易窮舉出x的確定值。
  • 謎題友好:這個特性聽起來是人畜無害的,其實用我的話來解釋就是盲目的窮舉一個巨大無比的數據集,而要求是要找到一個小區域內的值。用人話來說就是,給你一個地球這麼大的區域,讓你通過窮舉來尋找你家小區或者一個超市或者一個城市的區域,這個所要尋找的區域往往越小,難度越高(正常人都能看出來)。而這個謎題取自哪裏也非常重要,謎題往往取自高階最小熵分佈,這樣就保證了沒有捷徑能走。

2. 常見的哈希函數構造法

  • 相信大家都接觸過數據結構,在那裏面講到過很多種構建哈希函數的方法和存儲方式,咱也列舉一下(有的是複製粘貼的,因爲在數據結構中都有講到)。
  • 百度詞條哈希表和相應問題處理方法

2.1 直接尋址法

  • 取關鍵字或關鍵字的某個線性函數值爲散列地址。即hash(k) = k 或 hash(k) = a · k + b,其中a、b爲常數(這種散列函數叫做自身函數)。

2.2 數字分析法

  • 這種方法是對重複性比較高的位進行查找,然後多選幾位組成哈希地址,避免衝突增加。

2.3 平方取中法

  • 取關鍵字平方後的中間幾位爲哈希地址。通常在選定哈希函數時不一定能知道關鍵字的全部情況,取其中的哪幾位也不一定合適,而一個數平方後的中間幾位數和數的每一位都相關,由此使隨機分佈的關鍵字得到的哈希地址也是隨機的。取的位數由表長決定。

2.4 摺疊法

  • 將關鍵字分割成位數相同的幾部分(最後一部分的位數可以不同),然後取這幾部分的疊加和(捨去進位)作爲哈希地址。

2.5 隨機數法

  • 選擇一個隨機函數,取關鍵字的隨機函數值作爲它的哈希地址,即H(key)=random(key),其中random爲隨機函數。通常用於關鍵字長度不等時的場合。

2.6 除留餘數法

  • 取關鍵字被某個不大於哈希表表長m的數p除後所得餘數爲哈希地址。即H(key)=key MOD p(p<=m)。
  • 不僅可以對關鍵字直接取模,也可在摺疊法、平方取中法等運算之後取模。對p的選擇很重要,一般取素數或m,若p選擇不好,容易產生衝突。

2.7 加密哈希函數

  • 這裏介紹安全哈希算法(SHA - 256),主要是被比特幣採用的哈希函數。
  • 與它相關的概念叫壓縮函數(compression function)。在通用術語中,將接受固定長度的哈希函數轉化爲可接受任意長度輸入的哈希函數,這種轉換過程叫MD(Merkle-Damgard)變換。一般來說這種基礎型,可用於固定長度,並且具備碰撞阻力的哈希函數就是壓縮函數。
  • SHA - 256就是利用了壓縮函數將一個768位的輸入壓縮成256位的輸出,每一個區塊的大小是512位。
  • 對於以上所說的知識,可以在百度上搜,或者看區塊鏈的書。

3. 哈希函數總結

  • 哈希函數並不是越複雜越好,而是根據需求進行設計和使用,因爲哈希函數越複雜,時間消耗越長,對性能也有一定的影響。

二. 哈希查找

1. 操作步驟

  • 用給定的哈希函數構造哈希表。
  • 根據選擇的衝突處理方法解決地址衝突。
  • 在哈希表的基礎上執行哈希查找。

2.哈希表的查找

  • 哈希表的查找效率主要取決於哈希函數的構造方式、處理衝突的方式和裝填因子。

2.1 哈希衝突

  • 其實原理就是上面講的碰撞,爲了處理衝突,有這幾種處理方法:
  • 百度詞條哈希查找,這裏面講的還可以,有資源的可以在網上找具體操作,當然數據結構中的hash也講過這幾個方法,可以去找課件和書。

2.1.1 開放尋址法

  • 如果產生衝突,就找個空地址塞進去,當然要保證散列地址足夠大。
  • 這種方法細分爲3種,分別是線性探測再散列、二次探測再散列、僞隨機探測再散列,詳細的設計方法和原理在上面的鏈接裏也有。

2.1.2 鏈地址法

  • 將所有同關鍵字的記錄存儲在一個單鏈表中,稱這種表爲同義詞子表,在散列表中只存儲所有同義詞子表的頭指針。
  • 這種方法有點像用鏈表構成樹。

2.1.3 再散列法

  • 提前準備多個散列函數,如果其中一個找不到合適的位置,那就換一個散列函數。

2.1.4 建立公共溢出區

  • 粗暴方式,只要發生衝突就填進公共溢出區。

2.2 裝填因子

  • 散列表的裝填因子定義爲:α= 填入表中的元素個數 / 散列表的長度
  • α是散列表裝滿程度的標誌因子。
  • 由於表長是定值,α與填入表中的元素個數成正比,所以,α越大,填入表中的元素較多,產生衝突的可能性就越大;α越小,填入表中的元素較少,產生衝突的可能性就越小。
  • 實際上,散列表的平均查找長度是裝填因子α的函數,只是不同處理衝突的方法有不同的函數。

三. 總結

  • HashMap就是由數組+鏈表組合成的,也就是鏈地址法,在這篇裏主要講的就是哈希相關的東西,HashMap改天再說。
  • 哈希函數的構造不是越複雜越好,合適就行了,因爲不同的應用由不同的需求,根據需求選擇合適的結構就行了,性能方面也要考慮,例如HashMap只要儘量的減少它的鏈表就能提高它執行的性能。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章