一、直觀的資料去重方式
通常我們採用如下演算法對一組長度為n的資料d進行去重時。
s1.在資料中取出第x個資料(1≤xs2.在資料中取出第y個資料(xs3.比較d[x]和d[y],若相同丟棄d[y],重複s2,s3直到y=n
s4.重複s1,s2,s3直到x=n-1
此演算法時間複雜度近似t(n)=o(1/2n²),空間需求為size(d)。
假設現有一組資料d,單條長度500位元組,共有108條,有一台計算機,每秒處理106次資料對比。由此可以計算,該次去重共需要的儲存空間為s=108*500=5*1010=50g,所需要的時間t=1/2*(108)²*1/106=5*109秒≈158年
由此可見,對於大量的資料去重任務來說,這個演算法是不可行的。
當然這個演算法也可以通過提公升硬體來減少儲存和處理時間,如:將資料儲存在磁碟,在需要的時候載入到記憶體,使用磁碟陣列來增加讀取速度,來解決儲存問題。增加cpu核數來增加比對速度來減少時間等。但這些都增加了成本
二、布隆過濾器
布隆過濾器是由burton howard bloom於2023年提出,他是一種space efficient的概率模型資料結構,用於判斷乙個元素是否在集合中。
乙個空的布隆過濾器是乙個m bit的bitmap,每一位都初始化為0。布隆過濾器定義有k個hash函式,對輸入的資料生成k個hash值,定義有乙個map函式將k個hash值對映到bitmap的k個位。如下圖:
存入時將資料對應的bitmap中的k個位都置為1,檢索時只需要比對資料對應的k個位是否都為1。布隆過濾器不允許從中刪除資料,因為刪除資料時可能會影響其他資料對應的位,造成刪除其他資料。
三、布隆過濾器的實現(python)
bloom.py
importrandom__init__ 中mapsize為bitmap的size,max_node_size為最大容納的資料個數,random_num生成隨機數個數,這裡使用偽隨機數來代替hash函式。frombitmapimportbitmap
class
bloomfilter:
def__init__
(self
, mapsize=
160000
, max_node_size=
10000
, random_num=8):
self
.m = mapsize
self
.n = max_node_size
self
.k = random_num
self
.bitmap = bitmap(
maxnum
=self
.m)
self
.count = 0;
pass
def
set(
self
, string):
calcmap =
self
.calcmap(string)
forxincalcmap:
self
.bitmap.set(x)
pass
def
test(
self
, string):
calcmap =
self
.calcmap(string)
forxincalcmap:
if notself
.bitmap.test(x):
return false
return true
def
calcmap(
self
, string):
r = random.random(string)
lv1random = [r.random()forxinrange
(self
.k)]
return[
int(random.random(x).random()*
self
.m)forxinlv1random]
set將輸入的資料存入到布隆過濾器
test測試輸入的資料是否在布隆過濾器章
calcmap計算輸入的資料對映到bitmap的位置
bitmap.py
importarray
class
bitmap(
object
):"""
bitmap class
"""bitmask= [
0x01
, 0x02
, 0x04
, 0x08
, 0x10
, 0x20
, 0x40
, 0x80
]bit_cnt = [
bin(i).count(
"1")foriinrange
(256
)]def__init__
(self
, maxnum=0):
"""create a bitmap
"""nbytes =
int((maxnum +
7) / 8)
self
.bitmap = array.array(
'b',
[0foriinrange
(nbytes)])
def
set(
self
, pos):
"""set the value of bit@pos to 1
"""self
.bitmap[
int(pos /
8)] |=
self
.bitmask[pos % 8]
def
test(
self
, pos):
"""return bit value
"""return(
self
.bitmap[
int(pos /
8)] &
self
.bitmask[pos %
8]) != 0
set為在bitmap特定索引處置1,
test為測試在bitmap特定索引處是否為1
四、利用布隆過濾器
我們可以採用以下演算法利用布隆過濾器來對一組長度為n的資料d去重
s1取第x個資料(1≤x≤n)
s2在布隆過濾器中檢索d[x]是否存在於布隆過濾器,若存在則丟棄
s3將d[x]存入到布隆過濾器
s4重複s1-3直到x=n
這個演算法的時間複雜度t(n)=o(n),空間需求s=m/8,m為bitmap的總位數,m>n且m/n>k,n為資料d包含的資料條數,k為hash函式的個數。
在k=8,m/n=32時,對上文提到的資料進行去重處理,所需要的時間t=108/106=100秒,空間需求s=32*108/8=400m。相對於上文的演算法,改演算法可以大大節省時間和儲存空間。
python過濾器 布隆過濾器 python實現
布隆過濾器是什麼?在爬蟲爬取網頁的時候,我們會做的一件事情是判斷這個網頁是否之前已經爬取過。這個檢驗步驟在之前的文章裡我是用了乙個 集合 來儲存已經爬取過的網頁,而在計算機當中,使用hash表來儲存。hash表的好處就是能夠快速定位,而它的缺點也眾所皆知,就是儲存空間的浪費。為什麼會浪費儲存空間呢?...
布隆過濾器
布隆過濾器 bloom filter 是1970年由布隆提出的。它實際上是乙個很長的二進位制向量和一系列隨機對映函式。布隆過濾器可以用於檢索乙個元素是否在乙個集合中。它的優點是空間效率和查詢時間都遠遠超過一般的演算法,缺點是有一定的誤識別率和刪除困難。如果想要判斷乙個元素是不是在乙個集合裡,一般想到...
布隆過濾器
布隆過濾器的概念 如果想要判斷乙個元素是不是在乙個集合裡,一般想到的是將所有元素儲存起來,然後通過比較確定。鍊錶,樹等等資料結構都是這種思路.但是隨著集合中元素的增加,我們需要的儲存空間越來越大,檢索速度也越來越慢 o n o logn 不過世界上還有一種叫作雜湊表 又叫 雜湊表,hash tabl...