雜湊函式
雜湊函式
- 輸入域無窮大
- 輸出域有邊界(1<<64)
- 輸入相同的樣本,一定得到相同的輸出結果
- 不同的樣本,有可能發生碰撞(結果相同)
- 在輸入源樣本量足夠大的情況下,結果將在輸出域上均勻分佈。
雜湊函式的離散性,能夠打亂樣本規律。
雜湊函式實現的方式
通過大量的異或,交換。打亂原本的樣本結構,放大樣本差異。
生成不相關的hash函式
正常一個hash函式的結果h為16位元組,每個位元組為一個16進位制(0~9,a~f中的)的任意值。將前8為作為h1,後8位作為h2。
通過h1 + k * h2生成一個新的結果。並且他將於原本的h無關。
雜湊函式特性的使用
大任務(hash % n
)分流成N個小任務。
經典雜湊表
經典的雜湊表結構通過陣列+連結串列的結構實現
雜湊表的結構
雜湊表的本質是一個陣列,陣列中每一個元素稱為一個箱子(bin),箱子中存放的是連結串列,連結串列節點中存放的鍵值對。
雜湊表儲存的過程
- 根據 key 計算出它的雜湊值 h。
- 假設箱子的個數為 n,那麼這個鍵值對應該放在第 (h % n) 個箱子中。
- 雜湊值h相同,通過連結串列儲存在同一個箱子中。
自動擴容
當雜湊表的效率因陣列量過大造成損耗,進行擴容並重新簡歷雜湊表
- 當某一個連結串列上的節點個數超過某個係數(負載因子),將進行擴容。
- 擴容可以是離線的(在非活躍狀態下進行擴容,重建雜湊表,重建結束後再使用新的雜湊表)
增刪改查的時間複雜度
對key進行hash,通過下標定址,查詢一個短連結串列均為常數時間操作。
時間複雜度===》O(1)
設計RandomPool結構
【題目】 設計一種結構,在該結構中有如下三個功能:
insert(key):將某個key加入到該結構,做到不重複加入。
delete(key):將原本在結構中的某個key移除。
getRandom(): 等概率隨機返回結構中的任何一個key。
【要求】 Insert、delete和getRandom方法的時間複雜度都是 O(1)
需要的結構:
兩個雜湊表,一個size變數計數
每次新增一個新的key23:
- 令size+1
- 將key23作為key,size作為value,記錄在第一個hashMap中
- 將size作為key,key23作為value,記錄在第二個haskMap中
讀取隨機key時,在第二個hashMap中用(1~size)作為key進行查詢返回
刪除key時,將末尾元素與刪除元素的index互換,刪除該元素。並將size-1。
布隆過濾器BloomFilter
布隆過濾器可以用於檢索一個元素是否在一個集合中。它的優點是空間效率和查詢時間都比一般的演算法要好的多,缺點是有一定的誤識別率和刪除困難。
可以解決爬蟲去重,黑名單問題。
實現一個bit型別陣列,將資料容量擴容
- 建立一個[基礎型別]型別的陣列
- 一個Int型別可以表示成32bit的二進位制資料,long型別則是64bit
- 一個[Int]陣列將是普通陣列的32倍容量
以一個100長度的Int陣列([bit]長度為3200)arr為例,當我們想修改第3000個bit:
-
3000/32獲得arr組的indexI
-
3000%32獲得arr[indexI]下,[bit]想要修改的indexB
-
通過
arr[indexI] = (arr[IndexI] | (1 << indexB))
進行修改1
左移indexB
個位置,將會變成00000010000
這種形式。然後與原本的arr[IndexI]
相交,對應位置將會被修改為1
可以用矩陣,將資料容量繼續擴容
以Int陣列為例
[1000]的陣列可以代表3200個bit位
[1000][1000]的矩陣則可以代表3200*1000個bit位
布隆過濾器的實現
- 準備一個長度為m的陣列,通常是bit陣列
- 將指定的key用一個hash函式求出hash值
- 將hash % m 確定一個位置,並將該位置從0修改成1
- 重複用k不相關個hash函式,確定多個位置並修改成1
經過這個處理之後的陣列,就是布隆過濾器。
- 當一個新的key進行查詢時,也通過多次hash計算,確定是否存在於布隆過濾器
布隆過濾器的誤差
由於陣列長度的限制,有可能導致描黑位置過多,導致失誤命中概率過高。
通過調整hash函式個個數k,以及陣列長度m。可以得到不同的失誤率。
布隆過濾器的優勢
由於內部通過hash函式定位,最終過濾器所佔記憶體的大小與單樣本的記憶體大小無關。
比如一個長度為1000000的字串,也並不需要存進陣列。只需要在陣列中修改k個位置即可。
布隆過濾器長度公式
[bit]的長度m,樣本量n,預期失誤率p,ln是自然對數
布隆過濾器hash函式個數公式
布隆過濾器真是失誤率
當m和k確定之後的失誤率
經典伺服器抗壓結構
通過對key進行hash % n 可以將讀寫的壓力均勻的分佈給三個伺服器
而這種結構,當加入新的伺服器或減少原有的伺服器。我們需要像hashMap的自動擴容一樣需要重建整個對映。
一致性雜湊
經典抗壓結構在擴容時,需要對資料做全量遷移,計算每一條資料的歸屬。
一致性雜湊可以降低資料遷移的代價,同時保證負載均衡。
正常的工作流程
- 根據關鍵資訊計算出三個負載伺服器的hashCode:h1,h2,h3。
- 將三個值交由前方的前段伺服器持有
- 當進行讀寫操作時,對key進行hash,用二分的方式尋找順時針方向最近的負載伺服器並交付。
資料遷移的流程
只需要將黑色部分資料從1號伺服器遷移給4號伺服器即可。
虛擬節點技術
通過將每個伺服器分配N個虛擬節點對映,讓整個環上的分割區域約等於平均。
並查集結構
非常快的:
- 確定兩個元素是否屬於同一集合
- 合併兩個元素所在的集合
集合結構以樹的形式實現,樹的頭部元素作為代表元
,只要某元素所在樹的代表元
相同,二者所在的集合就相同。
在合併的過程中,將其中一個集合樹的頭部代表元
的上一級指向另一個代表元
即可。
具體可以參閱其他的帖子: