欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++ BloomFilter布隆過(guò)濾器應(yīng)用及概念詳解

 更新時(shí)間:2023年03月08日 10:17:19   作者:平凡的人1  
布隆過(guò)濾器是由布?。˙urton Howard Bloom)在1970年提出的 一種緊湊型的、比較巧妙的概率型數(shù)據(jù)結(jié)構(gòu),特點(diǎn)是高效地插入和查詢,可以用來(lái)告訴你 “某樣?xùn)|西一定不存在或者可能存在”,它是用多個(gè)哈希函數(shù),將一個(gè)數(shù)據(jù)映射到位圖結(jié)構(gòu)中

一、布隆過(guò)濾器概念

布隆過(guò)濾器是由布?。˙urton Howard Bloom)在1970年提出的 一種緊湊型的、比較巧妙的概率型數(shù)據(jù)結(jié)構(gòu),特點(diǎn)是高效地插入和查詢,可以用來(lái)告訴你 “某樣?xùn)|西一定不存在或者可能存在”,它是用多個(gè)哈希函數(shù),將一個(gè)數(shù)據(jù)映射到位圖結(jié)構(gòu)中。此種方式不僅可以提升查詢效率,也可以節(jié)省大量的內(nèi)存空間 .

位圖的優(yōu)點(diǎn)是節(jié)省空間,快,缺點(diǎn)是要求范圍相對(duì)集中,如果范圍分散,空間消耗上升,同時(shí)只能針對(duì)整型,字符串通過(guò)哈希轉(zhuǎn)化成整型,再去映射,對(duì)于整型沒(méi)有沖突,因?yàn)檎褪怯邢薜模成湮ㄒ坏奈恢?,但是?duì)于字符串來(lái)說(shuō),是無(wú)限的,會(huì)發(fā)生沖突,會(huì)發(fā)生誤判:此時(shí)的情況的是不在是正確的,在是不正確的,因?yàn)榭赡懿粊?lái)是不在的,但是位置跟別人發(fā)生沖突,發(fā)生誤判

此時(shí)布隆過(guò)濾器就登場(chǎng)了,可以降低誤判率:讓一個(gè)值映射多個(gè)位置,但是并不是消除誤判

可能還是會(huì)出現(xiàn)誤判:

雖然布隆過(guò)濾器還是會(huì)出現(xiàn)誤判,因?yàn)檫@個(gè)數(shù)據(jù)的比特位被其他數(shù)據(jù)所占,但是判斷一個(gè)數(shù)據(jù)不存在是準(zhǔn)確,不存在就是0!

布隆過(guò)濾器改進(jìn):映射多個(gè)位置,降低誤判率(位置越多,消耗也越多)

如果布隆過(guò)濾器長(zhǎng)度比較小,比特位很快會(huì)被占為1,誤判率自然會(huì)上升,所以布隆過(guò)濾器的長(zhǎng)度會(huì)影響誤判率,理論上來(lái)說(shuō),如果一個(gè)值映射的位置越多,則誤判的概率越小,但是并不是位置越多越好,空間也會(huì)消耗:大佬們自然也能夠想得到,所以有公式:

我們可以來(lái)估算一下,假設(shè)用 3 個(gè)哈希函數(shù),即K=3,ln2 的值我們?nèi)?0.7,那么 m 和 n 的關(guān)系大概是 m = n×k/ln2=4.2n ,也就是過(guò)濾器長(zhǎng)度應(yīng)該是插入元素個(gè)數(shù)的 4 -5倍

二、布隆過(guò)濾器應(yīng)用

不需要一定準(zhǔn)確的場(chǎng)景。比如游戲注冊(cè)時(shí)候的昵稱的判重:如果不在那就是不在,沒(méi)被使用,在的話可能會(huì)被誤判。

提高查找效率:客戶端中查找一個(gè)用戶的ID與服務(wù)器中的是否相同,在增加一層布隆過(guò)濾器提高查找效率:

三、布隆過(guò)濾器實(shí)現(xiàn)

布隆過(guò)濾器的插入元素可能是字符串,也可能是其他類型,只要提供對(duì)應(yīng)的哈希函數(shù)將該類型的數(shù)據(jù)轉(zhuǎn)換成整型就可以了。

一般情況下布隆過(guò)濾器都是用來(lái)處理字符串的,所以布隆過(guò)濾器可以實(shí)現(xiàn)為一個(gè)模板類,將模板參數(shù) T 的缺省類型設(shè)置為 string:

template <size_t N,size_t X = 5,class K=string,
		class HashFunc1 = BKDRHash,
		class HashFunc2 = APHash,
		class HashFunc3 = DJBHash>
class BloomFilter
	{
    public:
    private:
		bitset<N * X> _bs;
	};

這里布隆過(guò)濾器提供三個(gè)哈希函數(shù),由于布隆過(guò)濾器一般處理的是字符串類型的數(shù)據(jù),所以我們默認(rèn)提供幾個(gè)將字符串轉(zhuǎn)換成整型的哈希函數(shù):選取綜合評(píng)分最高的 BKDRHash、APHash 和 DJBHash這三種哈希算法:

   struct BKDRHash
	{
		size_t operator()(const string& key)
		{
			size_t hash = 0;
			for (auto ch : key)
			{
				hash *= 131;
				hash += ch;
			}
			return hash;
		}
	};
	struct APHash
	{
		size_t operator()(const string& key)
		{
			size_t hash = 0;
			int i = 0;
			for (auto ch : key)
			{
				if ((i & 1) == 0)
				{
					hash ^= ((hash << 7) ^ (ch) ^ (hash >> 3));
				}
				else
				{
					hash ^= (~((hash << 11) ^ (ch) ^ (hash >> 5)));
				}
				++i;
			}
			return hash;
		}
	};
	struct DJBHash
	{
		size_t operator()(const string& key)
		{
			size_t hash = 5318;
			for (auto ch : key)
			{
				hash += (hash << 5) + ch;
			}
			return hash;
		}
	};

1.插入

布隆過(guò)濾器復(fù)用bitset的 set 接口用于插入元素,插入元素時(shí),我們通過(guò)上面的三個(gè)哈希函數(shù)分別計(jì)算出該元素對(duì)應(yīng)的三個(gè)比特位,然后在位圖中設(shè)置為1即可:

        void set(const K& key)
		{
			size_t hash1 = HashFunc1()(key) % (N * X);
			size_t hash2 = HashFunc2()(key) % (N * X);
			size_t hash3 = HashFunc3()(key) % (N * X);
			_bs.set(hash1);
			_bs.set(hash2);
			_bs.set(hash3);
			_bs.set(hash4);
		}

2.查找

通過(guò)三個(gè)哈希函數(shù)分別算出對(duì)應(yīng)元素的三個(gè)哈希地址,得到對(duì)應(yīng)的比特位,然后去判斷這三個(gè)比特位是否都被設(shè)置成了1

如果出現(xiàn)一個(gè)比特位未被設(shè)置成1說(shuō)明該元素一定不存在,也就是如果一個(gè)比特位為0就是false;而如果三個(gè)比特位全部都被設(shè)置,則return true表示該元素已經(jīng)存在(注:可能會(huì)出現(xiàn)誤判)

        bool test(const K& key)
		{
			size_t hash1 = HashFunc1()(key) % (N * X);
			if (!_bs.test(hash1))
			{
				return false;
			}
			size_t hash2 = HashFunc2()(key) % (N * X);
			if (!_bs.test(hash2))
			{
				return false;
			}
			size_t hash3 = HashFunc3()(key) % (N * X);
			if (!_bs.test(hash3))
			{
				return false;
			}
			return true;
		}

3.刪除

布隆過(guò)濾器一般沒(méi)有刪除,因?yàn)椴悸∵^(guò)濾器判斷一個(gè)元素是會(huì)存在誤判,此時(shí)無(wú)法保證要?jiǎng)h除的元素在布隆過(guò)濾器中,如果此時(shí)將位圖中對(duì)應(yīng)的比特位清0,就會(huì)影響到其他元素了:

這時(shí)候我們只需要在每個(gè)比特位加一個(gè)計(jì)數(shù)器,當(dāng)存在插入操作時(shí),在計(jì)數(shù)器里面進(jìn)行 ++,刪除后對(duì)該位置進(jìn)行 -- 即可

但是布隆過(guò)濾器的本來(lái)目的就是為了提高效率和節(jié)省空間,在每個(gè)比特位增加額外的計(jì)數(shù)器,空間消耗那就更多了

四、布隆過(guò)濾器優(yōu)缺

優(yōu)

\1. 增加和查詢?cè)氐臅r(shí)間復(fù)雜度為:O(K), (K為哈希函數(shù)的個(gè)數(shù),一般比較小),與數(shù)據(jù)量大小無(wú)關(guān)

\2. 哈希函數(shù)相互之間沒(méi)有關(guān)系,方便硬件并行運(yùn)算

\3. 布隆過(guò)濾器不需要存儲(chǔ)元素本身,在某些對(duì)保密要求比較嚴(yán)格的場(chǎng)合有很大優(yōu)勢(shì)

\4. 在能夠承受一定的誤判時(shí),布隆過(guò)濾器比其他數(shù)據(jù)結(jié)構(gòu)有這很大的空間優(yōu)勢(shì)

\5. 數(shù)據(jù)量很大時(shí),布隆過(guò)濾器可以表示全集,其他數(shù)據(jù)結(jié)構(gòu)不能

\6. 使用同一組散列函數(shù)的布隆過(guò)濾器可以進(jìn)行交、并、差運(yùn)算

\1. 有誤判率,不能準(zhǔn)確判斷元素是否在集合中(補(bǔ)救方法:再建立一個(gè)白名單,存儲(chǔ)可能會(huì)誤判的數(shù)據(jù))

\2. 不能獲取元素本身

\3. 一般情況下不能從布隆過(guò)濾器中刪除元素

五、結(jié)語(yǔ)

給兩個(gè)文件,分別有100億個(gè)query,我們只有1G內(nèi)存,如何找到兩個(gè)文件交集?分別給出精確算法和近似算法?

近似算法:利用布隆過(guò)濾器,交集的就一定會(huì)進(jìn)去,但是可能會(huì)存在誤判:不同的也會(huì)進(jìn)去,這是近似

精準(zhǔn)算法:query一般是查詢指令,比如可能是網(wǎng)絡(luò)請(qǐng)求,或者是一個(gè)數(shù)據(jù)庫(kù)sql語(yǔ)句

100億個(gè)query,假設(shè)平均每個(gè)query是50byte,則100億個(gè)query那就是合計(jì)500GB

相同的query,是一定進(jìn)入相同編號(hào)的小文件,再對(duì)這些文件放進(jìn)內(nèi)存的兩個(gè)set中,編號(hào)相同的Ai和Bi小文件找交集即可

到此這篇關(guān)于C++ BloomFilter布隆過(guò)濾器應(yīng)用及概念詳解的文章就介紹到這了,更多相關(guān)C++ BloomFilter內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • VScode + keil開發(fā)環(huán)境搭建安裝使用過(guò)程

    VScode + keil開發(fā)環(huán)境搭建安裝使用過(guò)程

    這篇文章主要介紹了VScode + keil開發(fā)環(huán)境搭建及安裝使用過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-07-07
  • C++中std::is_object的具體使用

    C++中std::is_object的具體使用

    std::is_object是一種C++類型特性,其用途是判斷一個(gè)類型是否是一個(gè)對(duì)象類型,本文主要介紹了C++中std::is_object的具體使用,感興趣的可以了解一下
    2024-01-01
  • C語(yǔ)言示例代碼講解棧與隊(duì)列

    C語(yǔ)言示例代碼講解棧與隊(duì)列

    棧和隊(duì)列,嚴(yán)格意義上來(lái)說(shuō),也屬于線性表,因?yàn)樗鼈円捕加糜诖鎯?chǔ)邏輯關(guān)系為?"一對(duì)一"?的數(shù)據(jù),但由于它們比較特殊,本章講解分別用隊(duì)列實(shí)現(xiàn)棧與用棧實(shí)現(xiàn)隊(duì)列
    2022-05-05
  • C++靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)文件的生成和使用教程

    C++靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)文件的生成和使用教程

    庫(kù)文件是計(jì)算機(jī)上的一類文件,可以簡(jiǎn)單的把庫(kù)文件看成一種代碼倉(cāng)庫(kù),它提供給使用者一些可以直接拿來(lái)用的變量、函數(shù)和類,下面這篇文章主要給大家介紹了關(guān)于C++靜態(tài)庫(kù)與動(dòng)態(tài)庫(kù)文件的生成和使用的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • 利用Matlab一鍵生成工地海報(bào)特效

    利用Matlab一鍵生成工地海報(bào)特效

    這篇文章主要介紹了如何利用Matlab制作出工地海報(bào)的特效,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Matlab有一定幫助,需要的可以參考一下
    2022-03-03
  • C語(yǔ)言實(shí)現(xiàn)二叉樹遍歷的迭代算法

    C語(yǔ)言實(shí)現(xiàn)二叉樹遍歷的迭代算法

    這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)二叉樹遍歷的迭代算法,包括二叉樹的中序遍歷、先序遍歷及后序遍歷等,是非常經(jīng)典的算法,需要的朋友可以參考下
    2014-09-09
  • C語(yǔ)言的語(yǔ)法風(fēng)格與代碼書寫規(guī)范指南

    C語(yǔ)言的語(yǔ)法風(fēng)格與代碼書寫規(guī)范指南

    這篇文章主要介紹了C語(yǔ)言的語(yǔ)法風(fēng)格與代碼書寫規(guī)范指南,文中主張了一些諸如變量和結(jié)構(gòu)體的命名規(guī)范等細(xì)節(jié)方面的問(wèn)題,需要的朋友可以參考下
    2016-02-02
  • C++函數(shù)中return語(yǔ)句的使用方法

    C++函數(shù)中return語(yǔ)句的使用方法

    C++中的return語(yǔ)句是函數(shù)中一個(gè)重要的語(yǔ)句,return語(yǔ)句用于結(jié)束當(dāng)前正在執(zhí)行的函數(shù),并將控制權(quán)返回給調(diào)用此函數(shù)的函數(shù),需要的朋友可以了解下
    2012-12-12
  • C++中Boost的轉(zhuǎn)換函數(shù)

    C++中Boost的轉(zhuǎn)換函數(shù)

    這篇文章介紹了C++中Boost的轉(zhuǎn)換函數(shù),文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • 關(guān)于虛函數(shù)實(shí)現(xiàn)多態(tài)的原理及分析

    關(guān)于虛函數(shù)實(shí)現(xiàn)多態(tài)的原理及分析

    這篇文章主要介紹了C++中如何實(shí)現(xiàn)多態(tài)問(wèn)題,具有很好的參考價(jià)值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02

最新評(píng)論