国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【C++高階(六)】哈希的應(yīng)用--位圖&布隆過(guò)濾器

這篇具有很好參考價(jià)值的文章主要介紹了【C++高階(六)】哈希的應(yīng)用--位圖&布隆過(guò)濾器。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

??博主CSDN主頁(yè):杭電碼農(nóng)-NEO??
?
?專欄分類:C++從入門(mén)到精通?
?
??代碼倉(cāng)庫(kù):NEO的學(xué)習(xí)日記??
?
??關(guān)注我??帶你學(xué)習(xí)C++
? ????


【C++高階(六)】哈希的應(yīng)用--位圖&布隆過(guò)濾器,C++從入門(mén)到精通,c++,哈希算法,數(shù)據(jù)結(jié)構(gòu)

1. 前言

哈希最常用的應(yīng)用是unordered
系列的容器,但是當(dāng)面對(duì)海量數(shù)據(jù)
如100億個(gè)數(shù)據(jù)中找有沒(méi)有100這
個(gè)數(shù)時(shí),使用無(wú)序容器的話內(nèi)存放不下
所以哈希思想還有別的更重要的應(yīng)用!

本章重點(diǎn):

本篇文章著重講解哈希的應(yīng)用的
兩個(gè)容器,一個(gè)是位圖,一個(gè)是布隆
過(guò)濾器,并且模擬實(shí)現(xiàn)它們.最后會(huì)
講解如何使用這兩個(gè)容器來(lái)解決一
些海量數(shù)據(jù)的面試題問(wèn)題


2. 位圖的概念以及定義

請(qǐng)先看一道海量數(shù)據(jù)的面試題:

【C++高階(六)】哈希的應(yīng)用--位圖&布隆過(guò)濾器,C++從入門(mén)到精通,c++,哈希算法,數(shù)據(jù)結(jié)構(gòu)

如果要使用unordered_set來(lái)解決
40億個(gè)整數(shù),一個(gè)整數(shù)占4四節(jié),
總共大約占16個(gè)G的內(nèi)存空間
并且set容器中不止有整型數(shù)據(jù),還有
其他的數(shù)據(jù),所以不能用set!

而一個(gè)數(shù)在或不在可以用1/0來(lái)表示
也就是說(shuō)其實(shí)只需要一個(gè)比特位就可
以知道一個(gè)數(shù)在不在其中.
于是位圖橫空出世!

位圖概念:

所謂位圖,就是用每一位來(lái)存放某種狀態(tài),適用于海量數(shù)據(jù),數(shù)據(jù)無(wú)重復(fù)的場(chǎng)景。通常是用來(lái)判斷某個(gè)數(shù)據(jù)存不存在的

舉例說(shuō)明:

【C++高階(六)】哈希的應(yīng)用--位圖&布隆過(guò)濾器,C++從入門(mén)到精通,c++,哈希算法,數(shù)據(jù)結(jié)構(gòu)

判斷1~22中哪些數(shù)據(jù)是存在的
只需要用三個(gè)整型也就是24個(gè)
比特位的空間,同理,40億個(gè)數(shù)據(jù)
也用不著16G的內(nèi)存,使用0.5G
內(nèi)存的位圖即可判斷一個(gè)數(shù)在不在!


3. 位圖的模擬實(shí)現(xiàn)

先來(lái)看看庫(kù)中實(shí)現(xiàn)的位圖:
【C++高階(六)】哈希的應(yīng)用--位圖&布隆過(guò)濾器,C++從入門(mén)到精通,c++,哈希算法,數(shù)據(jù)結(jié)構(gòu)

模板參數(shù)N代表位圖的大小

位圖有三個(gè)主要的接口函數(shù):

  1. set: 將一個(gè)數(shù)據(jù)放入位圖中
  2. reset:將一個(gè)數(shù)據(jù)從位圖中刪掉
  3. test:檢測(cè)一個(gè)數(shù)據(jù)在不在位圖中

位圖本身就是一段連續(xù)的空間
所以用char類型數(shù)組來(lái)充當(dāng)位圖的
基本結(jié)構(gòu)是很符合情況的!

先將位圖框架寫(xiě)出來(lái):

template<size_t N>//N是所有數(shù)中的最大值
class bit_set
{
public:
	bit_set()
	{
		_bit.resize(N / 8 + 1, 0);
	}
	void set(size_t x)//將第x位變成1
	{}
	void reset(size_t x)//將第x位由1變0
	{}
	bool test(size_t x)
	{}
private:
	vector<char> _bit;
};

在寫(xiě)set,reset等函數(shù)時(shí),要先清除一點(diǎn),
那就是char類型的數(shù)組一個(gè)元素有八個(gè)
比特位,所以我們需要確定兩個(gè)位置:
一是此數(shù)據(jù)在哪一個(gè)數(shù)組元素中
二是此數(shù)據(jù)對(duì)應(yīng)此元素的第幾個(gè)比特位
下面我們畫(huà)個(gè)圖來(lái)推導(dǎo)一下公式:

【C++高階(六)】哈希的應(yīng)用--位圖&布隆過(guò)濾器,C++從入門(mén)到精通,c++,哈希算法,數(shù)據(jù)結(jié)構(gòu)

現(xiàn)在已經(jīng)能準(zhǔn)確的找到這個(gè)比特位了
那么怎樣將這個(gè)比特位變成0/1并且
不會(huì)影響到其他的比特位呢?下面分享
兩個(gè)很巧妙的方法,請(qǐng)大家細(xì)細(xì)品嘗:

template<size_t N>//N是所有數(shù)中的最大值
class bit_set
{
public:
	bit_set()
	{
		_bit.resize(N / 8 + 1, 0);
	}
	void set(size_t x)//將第x位變成1
	{
		//x/8->在第幾個(gè)char
		//x%8->在這個(gè)char的第幾個(gè)比特位
		size_t i = x / 8;
		size_t j = x % 8;
		_bit[i] |= (1 << j);//將x對(duì)應(yīng)的比特位變成1
	}
	void reset(size_t x)
	{
		size_t i = x / 8;
		size_t j = x % 8;
		_bit[i] &= ~(1 << j);//將x對(duì)應(yīng)的比特位變成0
	}
	bool test(size_t x)
	{
		size_t i = x / 8;
		size_t j = x % 8;
		return _bit[i] & (1 << j);
	}
private:
	vector<char> _bit;
};

關(guān)于代碼的解釋都在注釋中,請(qǐng)耐心觀看
必要時(shí)可以自己畫(huà)圖做做試驗(yàn)


4. 布隆過(guò)濾器的概念以及定義

位圖有一個(gè)缺陷,那就是只能判斷整型是否存在
遇見(jiàn)字符串等類型的數(shù)據(jù)就很難處理了

布隆過(guò)濾器的提出:

【C++高階(六)】哈希的應(yīng)用--位圖&布隆過(guò)濾器,C++從入門(mén)到精通,c++,哈希算法,數(shù)據(jù)結(jié)構(gòu)
布隆過(guò)濾器的概念:

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

舉例說(shuō)明:

【C++高階(六)】哈希的應(yīng)用--位圖&布隆過(guò)濾器,C++從入門(mén)到精通,c++,哈希算法,數(shù)據(jù)結(jié)構(gòu)
查找字符"美團(tuán)"是否存在時(shí),會(huì)找到
這三個(gè)綠色的位置,看看是否都為1

布隆過(guò)濾器的拓展閱讀:

布隆過(guò)濾器原理


5. 布隆過(guò)濾器模擬實(shí)現(xiàn)(一)

首先,布隆過(guò)濾器的底層也是位圖,所以
只需封裝一層即可實(shí)現(xiàn)一個(gè)布隆過(guò)濾器!

但實(shí)現(xiàn)布隆過(guò)濾器的關(guān)鍵有以下幾個(gè)

  • 一個(gè)字符串映射幾個(gè)位置?
  • 怎樣把字符串轉(zhuǎn)換為整數(shù)?

一般而言,一個(gè)字符串映射的越多,那么
誤判率就越低,但是映射過(guò)多會(huì)導(dǎo)致不同
的字符串映射到相同的位置,所以一般映射
三個(gè)位置,并且將字符串轉(zhuǎn)換為整數(shù)也就
需要三種不同的方法,我在網(wǎng)上找了一些
字符串轉(zhuǎn)整數(shù)的算法,請(qǐng)看下面的代碼:

//三個(gè)不同的字符串映射成整數(shù)的函數(shù)
struct HashBKDR
{
	size_t operator()(const string& key)
	{
		size_t val = 0;
		for (auto ch : key)
		{
			val *= 131;
			val += ch;
		}
		return val;
	}
};
struct HashAP
{
	size_t operator()(const string& key)
	{
		size_t hash = 0;
		for (size_t i = 0; i < key.size(); i++)
		{
			if ((i & 1) == 0)
				hash ^= ((hash << 7) ^ key[i] ^ (hash >> 3));
			else
				hash ^= (~((hash << 11) ^ key[i] ^ (hash >> 5)));
		}
		return hash;
	}
};
struct HashDJB
{
	size_t operator()(const string& key)
	{
		size_t hash = 5381;
		for (auto ch : key)
			hash += (hash << 5) + ch;
		return hash;
	}
};

將這三個(gè)仿函數(shù)傳入類,用于字符串轉(zhuǎn)整型

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

// N表示準(zhǔn)備要映射N(xiāo)個(gè)值
template<size_t N,
	class K = string, class Hash1 = HashBKDR, class Hash2 = HashAP, class Hash3 = HashDJB>
class Bloom_Filter
{
public:
	void set(const K& key)
	{
		size_t hash1 = Hash1()(key) % (_ratio * N);
		_bits->set(hash1);
		size_t hash2 = Hash2()(key) % (_ratio * N);
		_bits->set(hash2);
		size_t hash3 = Hash3()(key) % (_ratio * N);
		_bits->set(hash3);
	}

	bool test(const K& key)
	{
		size_t hash1 = Hash1()(key) % (_ratio * N);
		if (!_bits->test(hash1))
			return false; // 準(zhǔn)確的
		size_t hash2 = Hash2()(key) % (_ratio * N);
		if (!_bits->test(hash2))
			return false; // 準(zhǔn)確的
		size_t hash3 = Hash3()(key) % (_ratio * N);
		if (!_bits->test(hash3))
			return false;  // 準(zhǔn)確的
		return true; // 可能存在誤判
	}

	void reset(const K& key)//支持刪除操作的話,可能會(huì)把其他數(shù)據(jù)對(duì)應(yīng)的映射值刪除
	{}
private:
	const static size_t _ratio = 5;//開(kāi)的空間越大,誤判率越小
	std::bitset<_ratio* N>* _bits = new std::bitset<_ratio * N>;//標(biāo)準(zhǔn)庫(kù)中的位圖是在棧上開(kāi)辟的靜態(tài)數(shù)組,過(guò)大會(huì)棧溢出
};

6. 布隆過(guò)濾器模擬實(shí)現(xiàn)(二)

布隆過(guò)濾器的查找是一個(gè)很玄幻的過(guò)程:

分別計(jì)算每個(gè)哈希值對(duì)應(yīng)的比特位置存儲(chǔ)的是否為零,只要有一個(gè)為零,代表該元素一定不在哈希表中,否則可能在哈希表中

因?yàn)楣:瘮?shù)可能存在沖突的原因,如下:

【C++高階(六)】哈希的應(yīng)用--位圖&布隆過(guò)濾器,C++從入門(mén)到精通,c++,哈希算法,數(shù)據(jù)結(jié)構(gòu)
所以我們得出一個(gè)結(jié)論:

  • 布隆過(guò)濾器說(shuō)一個(gè)元素存在,那它可能存在
  • 布隆過(guò)濾器說(shuō)一個(gè)元素不在,那它一定不在

布隆過(guò)濾器的刪除操作:

如果你理解了上面的內(nèi)容,你一定能
明白布隆過(guò)濾器是不支持刪除的,因?yàn)?br> 刪除一個(gè)關(guān)鍵字時(shí)可能將其他的關(guān)鍵字
的一部分也給刪除了,因?yàn)橐粋€(gè)bit位
只能存儲(chǔ)一個(gè)二進(jìn)制信息!

【C++高階(六)】哈希的應(yīng)用--位圖&布隆過(guò)濾器,C++從入門(mén)到精通,c++,哈希算法,數(shù)據(jù)結(jié)構(gòu)


7. 處理海量數(shù)據(jù)的面試題

海量數(shù)據(jù)的處理,有對(duì)位圖的應(yīng)用
也有對(duì)布隆過(guò)濾器的應(yīng)用一步一步解析

位圖的應(yīng)用:

  1. 給100億個(gè)整數(shù),設(shè)法找到只出現(xiàn)一次的整數(shù)?
  2. 給兩個(gè)文件,分別有100億個(gè)整數(shù),只有1G內(nèi)存,如何找到兩個(gè)文件交集?
  3. 位圖應(yīng)用變形:一個(gè)文件有100億個(gè)int,1G內(nèi)存,設(shè)法找到出現(xiàn)次數(shù)不超過(guò)2次的所有整數(shù)

布隆過(guò)濾器的應(yīng)用:

  1. 給兩個(gè)文件,分別有100億個(gè)query,我們只有1G內(nèi)存,如何找到兩個(gè)文件交集?分別給出精確算法和近似算法
  2. 如何擴(kuò)展BloomFilter使得它支持刪除元素的操作

這些問(wèn)題大家可以下來(lái)想一想,有什么問(wèn)題歡迎私信


8. 總結(jié)

講到這里,哈希的所有內(nèi)容就已經(jīng)
講完了,所以無(wú)腦哈希無(wú)腦哈希,
但實(shí)際上要學(xué)好哈希還真得費(fèi)點(diǎn)腦子

海量數(shù)據(jù)得處理問(wèn)題在面試時(shí)也是
經(jīng)常問(wèn)的,希望同學(xué)們好好學(xué)扎實(shí)!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-752297.html


?? 下期預(yù)告:C++11新改動(dòng)??

到了這里,關(guān)于【C++高階(六)】哈希的應(yīng)用--位圖&布隆過(guò)濾器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【C++】哈希的應(yīng)用:位圖、哈希切分與布隆過(guò)濾器

    【C++】哈希的應(yīng)用:位圖、哈希切分與布隆過(guò)濾器

    需要云服務(wù)器等云產(chǎn)品來(lái)學(xué)習(xí)Linux的同學(xué)可以移步/--騰訊云--/--阿里云--/--華為云--/官網(wǎng),輕量型云服務(wù)器低至112元/年,新用戶首次下單享超低折扣。 ? 目錄 一、位圖 1、位圖的概念 2、大廠面試題 2.1位圖應(yīng)用(騰訊) 2.2位圖應(yīng)用 3、位圖的優(yōu)缺點(diǎn) 二、哈希切分 三、布隆過(guò)濾

    2023年04月09日
    瀏覽(39)
  • 【C++學(xué)習(xí)】哈希的應(yīng)用—位圖與布隆過(guò)濾器

    【C++學(xué)習(xí)】哈希的應(yīng)用—位圖與布隆過(guò)濾器

    文章簡(jiǎn)介 : 在這篇文章中,你會(huì)學(xué)習(xí)到關(guān)于哈希思想的最常見(jiàn)的兩個(gè)應(yīng)用,也就是 位圖 與 布隆過(guò)濾器 , 文章會(huì)講解位圖和布隆過(guò)濾器的概念,底層實(shí)現(xiàn),對(duì)應(yīng)的適應(yīng)的場(chǎng)景,以及相關(guān)經(jīng)典 海量數(shù)據(jù)面試題 及解析。 所謂位圖,就是用每一位來(lái)存放某種狀態(tài),適用于 海量

    2024年04月14日
    瀏覽(51)
  • C++進(jìn)階--哈希的應(yīng)用之位圖和布隆過(guò)濾器

    C++進(jìn)階--哈希的應(yīng)用之位圖和布隆過(guò)濾器

    哈希是一種映射的思想。 先來(lái)看一道題:給40億個(gè)不重復(fù)的無(wú)符號(hào)整數(shù),沒(méi)排序過(guò)。給一個(gè)無(wú)符號(hào)整數(shù),如何 快速判斷 一個(gè)數(shù) 是否在 這40億個(gè)數(shù)中。 首先想到的解法可能有這幾種: 解法1 :遍歷40億個(gè)數(shù),O(N) 解法2 :先排序,快排O( N l o g 2 N Nlog_2N Nl o g 2 ? N ),再利

    2024年02月22日
    瀏覽(43)
  • C++哈希hash:位圖、布隆過(guò)濾器的實(shí)現(xiàn)及應(yīng)用

    C++哈希hash:位圖、布隆過(guò)濾器的實(shí)現(xiàn)及應(yīng)用

    所謂位圖,就是用每一位來(lái)存放某種狀態(tài),適用于海量數(shù)據(jù),數(shù)據(jù)無(wú)重復(fù)的場(chǎng)景。通常是用 來(lái)判斷某個(gè)數(shù)據(jù)存不存在的。 當(dāng)我們想查找某一個(gè)數(shù)據(jù)是否存在或者是否處于某種狀態(tài)時(shí),相比于直接對(duì)存放數(shù)據(jù)的容器進(jìn)行遍歷查找,與原存放數(shù)據(jù)的容器所建立映射關(guān)系的位圖來(lái)

    2024年04月11日
    瀏覽(36)
  • 哈希思想應(yīng)用【C++】(位圖,布隆過(guò)濾器,海量數(shù)據(jù)處理面試題)

    哈希思想應(yīng)用【C++】(位圖,布隆過(guò)濾器,海量數(shù)據(jù)處理面試題)

    ?? 目錄 一,位圖 1. 位圖概念 2.實(shí)現(xiàn) 3. 測(cè)試題 位圖的優(yōu)缺點(diǎn) 二,布隆過(guò)濾器 1). 布隆過(guò)濾器提出 2). 概念 3). 布隆過(guò)濾器的查找 4). 布隆過(guò)濾器刪除(了解) 5). 布隆過(guò)濾器優(yōu)點(diǎn) 6).?布隆過(guò)濾器缺陷 三,海量數(shù)據(jù)面試題 1)哈希切割 我們首先由一道面試題來(lái)理解位圖 給40億個(gè)不

    2024年02月04日
    瀏覽(50)
  • 【C++】哈希(位圖,布隆過(guò)濾器)

    【C++】哈希(位圖,布隆過(guò)濾器)

    今天的內(nèi)容是哈希的應(yīng)用:位圖和布隆過(guò)濾器 目錄 一、位圖 1.位圖概念 2.位圖的應(yīng)用 二、哈希切分 三、布隆過(guò)濾器 1.布隆過(guò)濾器的概念 2.布隆過(guò)濾器的應(yīng)用 四、總結(jié) ? 今天的內(nèi)容從一道面試題開(kāi)始引入: 給40億個(gè)不重復(fù)的無(wú)符號(hào)整數(shù),沒(méi)排過(guò)序。給一個(gè)無(wú)符號(hào)整數(shù),如何

    2024年02月01日
    瀏覽(28)
  • 【C++】哈希位圖和布隆過(guò)濾器

    【C++】哈希位圖和布隆過(guò)濾器

    哈希位圖和布隆過(guò)濾器都是常用的概率數(shù)據(jù)結(jié)構(gòu),用于高效地判斷一個(gè)元素是否存在于一個(gè)集合當(dāng)中,但它們?cè)趯?shí)現(xiàn)方法和各自的優(yōu)缺點(diǎn)上有所區(qū)別。 哈希位圖 哈希位圖(Hash Bitmap)是由一個(gè)位數(shù)組構(gòu)成,每個(gè)元素(通常是一個(gè)整數(shù))被映射到位數(shù)組中的某個(gè)位置。對(duì)于集合

    2024年02月08日
    瀏覽(24)
  • 哈希的應(yīng)用--位圖和布隆過(guò)濾器

    哈希的應(yīng)用--位圖和布隆過(guò)濾器

    位圖(Bitset)是一種數(shù)據(jù)結(jié)構(gòu),用于表示一組布爾值,其中每個(gè)元素通常對(duì)應(yīng)于一個(gè)位或一個(gè)二進(jìn)制值,可以存儲(chǔ)0或1。位圖在計(jì)算機(jī)科學(xué)和計(jì)算機(jī)工程中經(jīng)常用于各種應(yīng)用,特別是在位級(jí)別的標(biāo)志、掩碼和快速查找中。以下是位圖的一些關(guān)鍵特點(diǎn): 二進(jìn)制表示 :位圖中的每

    2024年02月08日
    瀏覽(31)
  • 【C++雜貨鋪】再談哈希算法:位圖 | 布隆過(guò)濾器 | 哈希切分

    【C++雜貨鋪】再談哈希算法:位圖 | 布隆過(guò)濾器 | 哈希切分

    給40億個(gè)不重復(fù)的無(wú)符號(hào)整數(shù),沒(méi)排過(guò)序。給一個(gè)無(wú)符號(hào)整數(shù),如何快速判斷一個(gè)數(shù)是否在這40億個(gè)數(shù)中。 解決方案 : 遍歷 :遍歷這40億個(gè)整數(shù),去判斷該數(shù)是否在這40億個(gè)整數(shù)中。時(shí)間復(fù)雜度是 O ( N ) O(N) O ( N ) 。 set :用 set 將這40億個(gè)整數(shù)存起來(lái),然后去判斷這個(gè)數(shù)是否在

    2024年02月08日
    瀏覽(30)
  • 【數(shù)據(jù)結(jié)構(gòu)】盤(pán)點(diǎn)那些經(jīng)典的 [哈希面試題]【哈希切割】【位圖應(yīng)用】【布隆過(guò)濾器】(10)

    【數(shù)據(jù)結(jié)構(gòu)】盤(pán)點(diǎn)那些經(jīng)典的 [哈希面試題]【哈希切割】【位圖應(yīng)用】【布隆過(guò)濾器】(10)

    前言 大家好吖,歡迎來(lái)到 YY 滴 數(shù)據(jù)結(jié)構(gòu) 系列 ,熱烈歡迎! 本章主要內(nèi)容面向接觸過(guò)C++的老鐵 主要內(nèi)容含: 歡迎訂閱 YY 滴C++專欄!更多干貨持續(xù)更新!以下是傳送門(mén)! YY的《C++》專欄 YY的《C++11》專欄 YY的《Linux》專欄 YY的《數(shù)據(jù)結(jié)構(gòu)》專欄 YY的《C語(yǔ)言基礎(chǔ)》專欄 YY的《

    2024年02月04日
    瀏覽(64)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包