數據結構基礎--哈希表


哈希函數

哈希函數

  1. 輸入域無窮大
  2. 輸出域有邊界(1<<64)
  3. 輸入相同的樣本,必定獲得相同的輸出結果
  4. 不一樣的樣本,有可能發生碰撞(結果相同)
  5. 在輸入源樣本量足夠大的狀況下,結果將在輸出域上均勻分佈。

哈希函數的離散性,可以打亂樣本規律。html

哈希函數實現的方式

經過大量的異或,交換。打亂本來的樣本結構,放大樣本差別。算法

生成不相關的hash函數

正常一個hash函數的結果h爲16字節,每一個字節爲一個16進制(0~9,a~f中的)的任意值。將前8爲做爲h1,後8位做爲h2。數組

經過h1 + k * h2生成一個新的結果。而且他將於本來的h無關。服務器

哈希函數特性的使用

大任務(hash % n)分流成N個小任務。數據結構


經典哈希表

經典的哈希表結構經過數組+鏈表的結構實現負載均衡

哈希表的結構

哈希表的本質是一個數組,數組中每個元素稱爲一個箱子(bin),箱子中存放的是鏈表,鏈表節點中存放的鍵值對。dom

哈希表存儲的過程

  1. 根據 key 計算出它的哈希值 h。
  2. 假設箱子的個數爲 n,那麼這個鍵值對應該放在第 (h % n) 個箱子中。
  3. 哈希值h相同,經過鏈表存儲在同一個箱子中。

自動擴容

當哈希表的效率因數組量過大形成損耗,進行擴容並從新簡歷哈希表函數

  1. 當某一個鏈表上的節點個數超過某個係數(負載因子),將進行擴容。
  2. 擴容能夠是離線的(在非活躍狀態下進行擴容,重建哈希表,重建結束後再使用新的哈希表)

增刪改查的時間複雜度

對key進行hash,經過下標尋址,查找一個短鏈表均爲常數時間操做。設計

時間複雜度===》O(1)3d


設計RandomPool結構

【題目】 設計一種結構,在該結構中有以下三個功能:

  1. insert(key):將某個key加入到該結構,作到不重複加入。

  2. delete(key):將本來在結構中的某個key移除。

  3. getRandom(): 等機率隨機返回結構中的任何一個key。

【要求】 Insert、delete和getRandom方法的時間複雜度都是 O(1)

須要的結構:

兩個哈希表,一個size變量計數

每次添加一個新的key23:

  1. 令size+1
  2. 將key23做爲key,size做爲value,記錄在第一個hashMap中
  3. 將size做爲key,key23做爲value,記錄在第二個haskMap中

讀取隨機key時,在第二個hashMap中用(1~size)做爲key進行查詢返回

刪除key時,將末尾元素與刪除元素的index互換,刪除該元素。並將size-1。


布隆過濾器BloomFilter

布隆過濾器能夠用於檢索一個元素是否在一個集合中。它的優勢是空間效率和查詢時間都比通常的算法要好的多,缺點是有必定的誤識別率和刪除困難。

能夠解決爬蟲去重,黑名單問題。

實現一個bit類型數組,將數據容量擴容

  1. 創建一個[基礎類型]類型的數組
  2. 一個Int類型能夠表示成32bit的二進制數據,long類型則是64bit
  3. 一個[Int]數組將是普通數組的32倍容量

以一個100長度的Int數組([bit]長度爲3200)arr爲例,當咱們想修改第3000個bit:

  1. 3000/32得到arr組的indexI

  2. 3000%32得到arr[indexI]下,[bit]想要修改的indexB

  3. 經過arr[indexI] = (arr[IndexI] | (1 << indexB))進行修改

    1左移indexB個位置,將會變成00000010000這種形式。而後與本來的arr[IndexI]相交,對應位置將會被修改成1

能夠用矩陣,將數據容量繼續擴容

以Int數組爲例

[1000]的數組能夠表明3200個bit位

[1000][1000]的矩陣則能夠表明3200*1000個bit位

布隆過濾器的實現

  1. 準備一個長度爲m的數組,一般是bit數組
  2. 將指定的key用一個hash函數求出hash值
  3. 將hash % m 肯定一個位置,並將該位置從0修改爲1
  4. 重複用k不相關個hash函數,肯定多個位置並修改爲1

通過這個處理以後的數組,就是布隆過濾器。

  1. 當一個新的key進行查詢時,也經過屢次hash計算,肯定是否存在於布隆過濾器

布隆過濾器的偏差

因爲數組長度的限制,有可能致使描黑位置過多,致使失誤命中機率太高。

經過調整hash函數個個數k,以及數組長度m。能夠獲得不一樣的失誤率。

布隆過濾器的優點

因爲內部經過hash函數定位,最終過濾器所佔內存的大小與單樣本的內存大小無關。

好比一個長度爲1000000的字符串,也並不須要存進數組。只須要在數組中修改k個位置便可。

布隆過濾器長度公式

[bit]的長度m,樣本量n,預期失誤率p,ln是天然對數

布隆過濾器hash函數個數公式

布隆過濾器真是失誤率

當m和k肯定以後的失誤率


經典服務器抗壓結構

經過對key進行hash % n 能夠將讀寫的壓力均勻的分佈給三個服務器

而這種結構,當加入新的服務器或減小原有的服務器。咱們須要像hashMap的自動擴容同樣須要重建整個映射。


一致性哈希

經典抗壓結構在擴容時,須要對數據作全量遷移,計算每一條數據的歸屬。

一致性哈希能夠下降數據遷移的代價,同時保證負載均衡。

正常的工做流程

  1. 根據關鍵信息計算出三個負載服務器的hashCode:h1,h2,h3。
  2. 將三個值交由前方的前段服務器持有
  3. 當進行讀寫操做時,對key進行hash,用二分的方式尋找順時針方向最近的負載服務器並交付。

數據遷移的流程

只須要將黑色部分數據從1號服務器遷移給4號服務器便可。

虛擬節點技術

經過將每一個服務器分配N個虛擬節點映射,讓整個環上的分割區域約等於平均。


並查集結構

很是快的:

  1. 肯定兩個元素是否屬於同一集合
  2. 合併兩個元素所在的集合

集合結構以樹的形式實現,樹的頭部元素做爲表明元,只要某元素所在樹的表明元相同,兩者所在的集合就相同。 在合併的過程當中,將其中一個集合樹的頭部表明元的上一級指向另外一個表明元便可。

具體能夠參閱其餘的帖子:

數據結構4——並查集(入門)

數據結構--並查集的原理及實現


參考資料

左神牛課網算法課

相關文章
相關標籤/搜索